donut snapshot
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index d66c6e5..9c4ace1 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -413,41 +413,45 @@
synchronized (mLock) {
pw.println("Current Alarm Manager state:");
- if (mRtcWakeupAlarms.size() > 0) {
+ if (mRtcWakeupAlarms.size() > 0 || mRtcAlarms.size() > 0) {
pw.println(" ");
- pw.println(" Realtime wakeup alarms that are scheduled:");
- dumpAlarmList(pw, mRtcWakeupAlarms, " ", "RTC_WAKEUP");
+ pw.print(" Realtime wakeup (now=");
+ pw.print(System.currentTimeMillis()); pw.println("):");
+ if (mRtcWakeupAlarms.size() > 0) {
+ dumpAlarmList(pw, mRtcWakeupAlarms, " ", "RTC_WAKEUP");
+ }
+ if (mRtcAlarms.size() > 0) {
+ dumpAlarmList(pw, mRtcAlarms, " ", "RTC");
+ }
}
- if (mRtcAlarms.size() > 0) {
+ if (mElapsedRealtimeWakeupAlarms.size() > 0 || mElapsedRealtimeAlarms.size() > 0) {
pw.println(" ");
- pw.println(" Realtime alarms that are scheduled:");
- dumpAlarmList(pw, mRtcAlarms, " ", "RTC");
- }
- if (mElapsedRealtimeWakeupAlarms.size() > 0) {
- pw.println(" ");
- pw.println(" Elapsed realtime wakeup alarms that are scheduled:");
- dumpAlarmList(pw, mElapsedRealtimeWakeupAlarms, " ", "ELAPSED_REALTIME_WAKEUP");
- }
- if (mElapsedRealtimeAlarms.size() > 0) {
- pw.println(" ");
- pw.println(" Elapsed realtime alarms that are scheduled:");
- dumpAlarmList(pw, mElapsedRealtimeAlarms, " ", "ELAPSED_REALTIME");
+ pw.print(" Elapsed realtime wakeup (now=");
+ pw.print(SystemClock.elapsedRealtime()); pw.println("):");
+ if (mElapsedRealtimeWakeupAlarms.size() > 0) {
+ dumpAlarmList(pw, mElapsedRealtimeWakeupAlarms, " ", "ELAPSED_WAKEUP");
+ }
+ if (mElapsedRealtimeAlarms.size() > 0) {
+ dumpAlarmList(pw, mElapsedRealtimeAlarms, " ", "ELAPSED");
+ }
}
pw.println(" ");
- pw.println(" Broadcast ref count: " + mBroadcastRefCount);
+ pw.print(" Broadcast ref count: "); pw.println(mBroadcastRefCount);
pw.println(" ");
pw.println(" Alarm Stats:");
for (Map.Entry<String, BroadcastStats> be : mBroadcastStats.entrySet()) {
BroadcastStats bs = be.getValue();
- pw.println(" " + be.getKey());
- pw.println(" " + bs.aggregateTime + "ms running, "
- + bs.numWakeup + " wakeups");
+ pw.print(" "); pw.println(be.getKey());
+ pw.print(" "); pw.print(bs.aggregateTime);
+ pw.print("ms running, "); pw.print(bs.numWakeup);
+ pw.println(" wakeups");
for (Map.Entry<Intent.FilterComparison, FilterStats> fe
: bs.filterStats.entrySet()) {
- pw.println(" " + fe.getValue().count + " alarms: "
- + fe.getKey().getIntent());
+ pw.print(" "); pw.print(fe.getValue().count);
+ pw.print(" alarms: ");
+ pw.println(fe.getKey().getIntent().toShortString(true, false));
}
}
}
@@ -456,7 +460,8 @@
private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list, String prefix, String label) {
for (int i=list.size()-1; i>=0; i--) {
Alarm a = list.get(i);
- pw.println(prefix + label + " #" + i + ":");
+ pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
+ pw.print(": "); pw.println(a);
a.dump(pw, prefix + " ");
}
}
@@ -561,18 +566,24 @@
@Override
public String toString()
{
- return "Alarm{"
- + Integer.toHexString(System.identityHashCode(this))
- + " type " + type + " " + operation.getTargetPackage() + "}";
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("Alarm{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(" type ");
+ sb.append(type);
+ sb.append(" ");
+ sb.append(operation.getTargetPackage());
+ sb.append('}');
+ return sb.toString();
}
public void dump(PrintWriter pw, String prefix)
{
- pw.println(prefix + this);
- pw.println(prefix + "type=" + type + " when=" + when
- + " repeatInterval=" + repeatInterval
- + " count=" + count);
- pw.println(prefix + "operation=" + operation);
+ pw.print(prefix); pw.print("type="); pw.print(type);
+ pw.print(" when="); pw.print(when);
+ pw.print(" repeatInterval="); pw.print(repeatInterval);
+ pw.print(" count="); pw.println(count);
+ pw.print(prefix); pw.print("operation="); pw.println(operation);
}
}
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index de5d0ac..c50ae94 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -35,6 +35,7 @@
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.AttributeSet;
@@ -151,34 +152,57 @@
synchronized (mAppWidgetIds) {
int N = mInstalledProviders.size();
- pw.println("Providers: (size=" + N + ")");
+ pw.println("Providers:");
for (int i=0; i<N; i++) {
Provider p = mInstalledProviders.get(i);
AppWidgetProviderInfo info = p.info;
- pw.println(" [" + i + "] provder=" + info.provider
- + " min=(" + info.minWidth + "x" + info.minHeight + ")"
- + " updatePeriodMillis=" + info.updatePeriodMillis
- + " initialLayout=" + info.initialLayout + " zombie=" + p.zombie);
+ pw.print(" ["); pw.print(i); pw.print("] provider ");
+ pw.print(info.provider.flattenToShortString());
+ pw.println(':');
+ pw.print(" min=("); pw.print(info.minWidth);
+ pw.print("x"); pw.print(info.minHeight);
+ pw.print(") updatePeriodMillis=");
+ pw.print(info.updatePeriodMillis);
+ pw.print(" initialLayout=#");
+ pw.print(Integer.toHexString(info.initialLayout));
+ pw.print(" zombie="); pw.println(p.zombie);
}
N = mAppWidgetIds.size();
- pw.println("AppWidgetIds: (size=" + N + ")");
+ pw.println(" ");
+ pw.println("AppWidgetIds:");
for (int i=0; i<N; i++) {
AppWidgetId id = mAppWidgetIds.get(i);
- pw.println(" [" + i + "] appWidgetId=" + id.appWidgetId
- + " host=" + id.host.hostId + "/" + id.host.packageName + " provider="
- + (id.provider == null ? "null" : id.provider.info.provider)
- + " host.callbacks=" + (id.host != null ? id.host.callbacks : "(no host)")
- + " views=" + id.views);
+ pw.print(" ["); pw.print(i); pw.print("] id=");
+ pw.println(id.appWidgetId);;
+ pw.print(" hostId=");
+ pw.print(id.host.hostId); pw.print(' ');
+ pw.print(id.host.packageName); pw.print('/');
+ pw.println(id.host.uid);
+ if (id.provider != null) {
+ pw.print(" provider=");
+ pw.println(id.provider.info.provider.flattenToShortString());
+ }
+ if (id.host != null) {
+ pw.print(" host.callbacks="); pw.println(id.host.callbacks);
+ }
+ if (id.views != null) {
+ pw.print(" views="); pw.println(id.views);
+ }
}
N = mHosts.size();
- pw.println("Hosts: (size=" + N + ")");
+ pw.println(" ");
+ pw.println("Hosts:");
for (int i=0; i<N; i++) {
Host host = mHosts.get(i);
- pw.println(" [" + i + "] packageName=" + host.packageName + " uid=" + host.uid
- + " hostId=" + host.hostId + " callbacks=" + host.callbacks
- + " instances.size=" + host.instances.size() + " zombie=" + host.zombie);
+ pw.print(" ["); pw.print(i); pw.print("] hostId=");
+ pw.print(host.hostId); pw.print(' ');
+ pw.print(host.packageName); pw.print('/');
+ pw.print(host.uid); pw.println(':');
+ pw.print(" callbacks="); pw.println(host.callbacks);
+ pw.print(" instances.size="); pw.print(host.instances.size());
+ pw.print(" zombie="); pw.println(host.zombie);
}
}
}
@@ -716,7 +740,7 @@
throw new IllegalArgumentException("packageName and uid don't match packageName="
+ packageName);
}
- if (callingUid != packageUid) {
+ if (callingUid != packageUid && Process.supportsProcesses()) {
throw new IllegalArgumentException("packageName and uid don't match packageName="
+ packageName);
}
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
new file mode 100644
index 0000000..983329b
--- /dev/null
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -0,0 +1,430 @@
+/*
+ * Copyright (C) 2009 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.backup.BackupService;
+import android.backup.IBackupService;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.SparseArray;
+
+import android.backup.IBackupManager;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.lang.String;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+class BackupManagerService extends IBackupManager.Stub {
+ private static final String TAG = "BackupManagerService";
+ private static final boolean DEBUG = true;
+
+ private static final long COLLECTION_INTERVAL = 1000;
+ //private static final long COLLECTION_INTERVAL = 3 * 60 * 1000;
+
+ private static final int MSG_RUN_BACKUP = 1;
+
+ private Context mContext;
+ private PackageManager mPackageManager;
+ private final BackupHandler mBackupHandler = new BackupHandler();
+ // map UIDs to the set of backup client services within that UID's app set
+ private SparseArray<HashSet<ServiceInfo>> mBackupParticipants
+ = new SparseArray<HashSet<ServiceInfo>>();
+ // set of backup services that have pending changes
+ private class BackupRequest {
+ public ServiceInfo service;
+ public boolean fullBackup;
+
+ BackupRequest(ServiceInfo svc, boolean isFull) {
+ service = svc;
+ fullBackup = isFull;
+ }
+ }
+ // Backups that we haven't started yet.
+ private HashMap<ComponentName,BackupRequest> mPendingBackups = new HashMap();
+ // Backups that we have started. These are separate to prevent starvation
+ // if an app keeps re-enqueuing itself.
+ private ArrayList<BackupRequest> mBackupQueue;
+ private final Object mQueueLock = new Object();
+
+ private File mStateDir;
+ private File mDataDir;
+
+ public BackupManagerService(Context context) {
+ mContext = context;
+ mPackageManager = context.getPackageManager();
+
+ // Set up our bookkeeping
+ mStateDir = new File(Environment.getDataDirectory(), "backup");
+ mStateDir.mkdirs();
+ mDataDir = Environment.getDownloadCacheDirectory();
+
+ // Build our mapping of uid to backup client services
+ synchronized (mBackupParticipants) {
+ addPackageParticipantsLocked(null);
+ }
+
+ // Register for broadcasts about package install, etc., so we can
+ // update the provider list.
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addDataScheme("package");
+ mContext.registerReceiver(mBroadcastReceiver, filter);
+ }
+
+ // ----- Track installation/removal of packages -----
+ BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ if (DEBUG) Log.d(TAG, "Received broadcast " + intent);
+
+ Uri uri = intent.getData();
+ if (uri == null) {
+ return;
+ }
+ String pkgName = uri.getSchemeSpecificPart();
+ if (pkgName == null) {
+ return;
+ }
+
+ String action = intent.getAction();
+ if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+ synchronized (mBackupParticipants) {
+ Bundle extras = intent.getExtras();
+ if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
+ // The package was just upgraded
+ updatePackageParticipantsLocked(pkgName);
+ } else {
+ // The package was just added
+ addPackageParticipantsLocked(pkgName);
+ }
+ }
+ }
+ else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+ Bundle extras = intent.getExtras();
+ if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
+ // The package is being updated. We'll receive a PACKAGE_ADDED shortly.
+ } else {
+ synchronized (mBackupParticipants) {
+ removePackageParticipantsLocked(pkgName);
+ }
+ }
+ }
+ }
+ };
+
+ // ----- Run the actual backup process asynchronously -----
+
+ private class BackupHandler extends Handler implements ServiceConnection {
+ public void handleMessage(Message msg) {
+
+ switch (msg.what) {
+ case MSG_RUN_BACKUP:
+ // snapshot the pending-backup set and work on that
+ synchronized (mQueueLock) {
+ mBackupQueue = new ArrayList();
+ for (BackupRequest b: mPendingBackups.values()) {
+ mBackupQueue.add(b);
+ }
+ mPendingBackups = new HashMap<ComponentName,BackupRequest>();
+ // !!! TODO: start a new backup-queue journal file too
+ // WARNING: If we crash after this line, anything in mPendingBackups will
+ // be lost. FIX THIS.
+ }
+ startOneService();
+ break;
+ }
+ }
+
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ Log.d(TAG, "onServiceConnected name=" + name + " service=" + service);
+ IBackupService bs = IBackupService.Stub.asInterface(service);
+ processOneBackup(name, bs);
+ }
+
+ public void onServiceDisconnected(ComponentName name) {
+ // TODO: handle backup being interrupted
+ }
+ }
+
+ void startOneService() {
+ // Loop until we find someone to start or the queue empties out.
+ Intent intent = new Intent(BackupService.SERVICE_ACTION);
+ while (true) {
+ BackupRequest request;
+ synchronized (mQueueLock) {
+ int queueSize = mBackupQueue.size();
+ if (queueSize == 0) {
+ mBackupQueue = null;
+ // TODO: Anything else to do here?
+ return;
+ }
+ request = mBackupQueue.get(0);
+ // Take it off the queue when we're done.
+ }
+
+ intent.setClassName(request.service.packageName, request.service.name);
+ Log.d(TAG, "binding to " + intent);
+ try {
+ if (mContext.bindService(intent, mBackupHandler, Context.BIND_AUTO_CREATE)) {
+ Log.d(TAG, "awaiting service object for " + intent);
+ // success
+ return;
+ }
+ } catch (SecurityException ex) {
+ // Try for the next one.
+ Log.d(TAG, "error in bind", ex);
+ }
+ }
+ }
+
+ void processOneBackup(ComponentName name, IBackupService bs) {
+ try {
+ Log.d(TAG, "processOneBackup doBackup() on " + name);
+
+ BackupRequest request;
+ synchronized (mQueueLock) {
+ if (mBackupQueue == null) {
+ Log.d(TAG, "mBackupQueue is null. WHY?");
+ }
+ request = mBackupQueue.get(0);
+ }
+
+ // !!! TODO right now these naming schemes limit applications to
+ // one backup service per package
+ File savedStateName = new File(mStateDir, request.service.packageName);
+ File backupDataName = new File(mDataDir, request.service.packageName + ".data");
+ File newStateName = new File(mStateDir, request.service.packageName + ".new");
+
+ // In a full backup, we pass a null ParcelFileDescriptor as
+ // the saved-state "file"
+ ParcelFileDescriptor savedState = (request.fullBackup) ? null
+ : ParcelFileDescriptor.open(savedStateName,
+ ParcelFileDescriptor.MODE_READ_ONLY |
+ ParcelFileDescriptor.MODE_CREATE);
+
+ backupDataName.delete();
+ ParcelFileDescriptor backupData =
+ ParcelFileDescriptor.open(backupDataName,
+ ParcelFileDescriptor.MODE_READ_WRITE |
+ ParcelFileDescriptor.MODE_CREATE);
+
+ newStateName.delete();
+ ParcelFileDescriptor newState =
+ ParcelFileDescriptor.open(newStateName,
+ ParcelFileDescriptor.MODE_READ_WRITE |
+ ParcelFileDescriptor.MODE_CREATE);
+
+ // Run the target's backup pass
+ try {
+ // TODO: Make this oneway
+ bs.doBackup(savedState, backupData, newState);
+ } finally {
+ if (savedState != null) {
+ savedState.close();
+ }
+ backupData.close();
+ newState.close();
+ }
+
+ // !!! TODO: Now propagate the newly-backed-up data to the transport
+
+ // !!! TODO: After successful transport, delete the now-stale data
+ // and juggle the files so that next time the new state is passed
+ backupDataName.delete();
+ newStateName.renameTo(savedStateName);
+
+ } catch (FileNotFoundException fnf) {
+ Log.d(TAG, "File not found on backup: ");
+ fnf.printStackTrace();
+ } catch (RemoteException e) {
+ Log.d(TAG, "Remote target " + name + " threw during backup:");
+ e.printStackTrace();
+ } catch (Exception e) {
+ Log.w(TAG, "Final exception guard in backup: ");
+ e.printStackTrace();
+ }
+ synchronized (mQueueLock) {
+ mBackupQueue.remove(0);
+ }
+ mContext.unbindService(mBackupHandler);
+ }
+
+ // Add the backup services in the given package to our set of known backup participants.
+ // If 'packageName' is null, adds all backup services in the system.
+ void addPackageParticipantsLocked(String packageName) {
+ List<ResolveInfo> services = mPackageManager.queryIntentServices(
+ new Intent(BackupService.SERVICE_ACTION), 0);
+ addPackageParticipantsLockedInner(packageName, services);
+ }
+
+ private void addPackageParticipantsLockedInner(String packageName, List<ResolveInfo> services) {
+ for (ResolveInfo ri : services) {
+ if (packageName == null || ri.serviceInfo.packageName.equals(packageName)) {
+ int uid = ri.serviceInfo.applicationInfo.uid;
+ HashSet<ServiceInfo> set = mBackupParticipants.get(uid);
+ if (set == null) {
+ set = new HashSet<ServiceInfo>();
+ mBackupParticipants.put(uid, set);
+ }
+ if (DEBUG) {
+ Log.v(TAG, "Adding " + services.size() + " backup participants:");
+ for (ResolveInfo svc : services) {
+ Log.v(TAG, " " + svc + " : " + svc.filter);
+ }
+ }
+
+ set.add(ri.serviceInfo);
+ }
+ }
+ }
+
+ // Remove the given package's backup services from our known active set. If
+ // 'packageName' is null, *all* backup services will be removed.
+ void removePackageParticipantsLocked(String packageName) {
+ List<ResolveInfo> services = mPackageManager.queryIntentServices(
+ new Intent(BackupService.SERVICE_ACTION), 0);
+ removePackageParticipantsLockedInner(packageName, services);
+ }
+
+ private void removePackageParticipantsLockedInner(String packageName,
+ List<ResolveInfo> services) {
+ for (ResolveInfo ri : services) {
+ if (packageName == null || ri.serviceInfo.packageName.equals(packageName)) {
+ int uid = ri.serviceInfo.applicationInfo.uid;
+ HashSet<ServiceInfo> set = mBackupParticipants.get(uid);
+ if (set != null) {
+ set.remove(ri.serviceInfo);
+ if (set.size() == 0) {
+ mBackupParticipants.put(uid, null);
+ }
+ }
+ }
+ }
+ }
+
+ // Reset the given package's known backup participants. Unlike add/remove, the update
+ // action cannot be passed a null package name.
+ void updatePackageParticipantsLocked(String packageName) {
+ if (packageName == null) {
+ Log.e(TAG, "updatePackageParticipants called with null package name");
+ return;
+ }
+
+ // brute force but small code size
+ List<ResolveInfo> services = mPackageManager.queryIntentServices(
+ new Intent(BackupService.SERVICE_ACTION), 0);
+ removePackageParticipantsLockedInner(packageName, services);
+ addPackageParticipantsLockedInner(packageName, services);
+ }
+
+ // ----- IBackupManager binder interface -----
+
+ public void dataChanged(String packageName) throws RemoteException {
+ // Record that we need a backup pass for the caller. Since multiple callers
+ // may share a uid, we need to note all candidates within that uid and schedule
+ // a backup pass for each of them.
+
+ Log.d(TAG, "dataChanged packageName=" + packageName);
+
+ HashSet<ServiceInfo> targets = mBackupParticipants.get(Binder.getCallingUid());
+ Log.d(TAG, "targets=" + targets);
+ if (targets != null) {
+ synchronized (mQueueLock) {
+ // Note that this client has made data changes that need to be backed up
+ for (ServiceInfo service : targets) {
+ // validate the caller-supplied package name against the known set of
+ // packages associated with this uid
+ if (service.packageName.equals(packageName)) {
+ // Add the caller to the set of pending backups. If there is
+ // one already there, then overwrite it, but no harm done.
+ mPendingBackups.put(new ComponentName(service.packageName, service.name),
+ new BackupRequest(service, true));
+ // !!! TODO: write to the pending-backup journal file in case of crash
+ }
+ }
+
+ Log.d(TAG, "Scheduling backup for " + mPendingBackups.size() + " participants");
+ // Schedule a backup pass in a few minutes. As backup-eligible data
+ // keeps changing, continue to defer the backup pass until things
+ // settle down, to avoid extra overhead.
+ mBackupHandler.sendEmptyMessageDelayed(MSG_RUN_BACKUP, COLLECTION_INTERVAL);
+ }
+ }
+ }
+
+ // Schedule a backup pass for a given package, even if the caller is not part of
+ // that uid or package itself.
+ public void scheduleFullBackup(String packageName) throws RemoteException {
+ // !!! TODO: protect with a signature-or-system permission?
+ HashSet<ServiceInfo> targets = new HashSet<ServiceInfo>();
+ synchronized (mQueueLock) {
+ int numKeys = mBackupParticipants.size();
+ for (int index = 0; index < numKeys; index++) {
+ int uid = mBackupParticipants.keyAt(index);
+ HashSet<ServiceInfo> servicesAtUid = mBackupParticipants.get(uid);
+ for (ServiceInfo service: servicesAtUid) {
+ if (service.packageName.equals(packageName)) {
+ mPendingBackups.put(new ComponentName(service.packageName, service.name),
+ new BackupRequest(service, true));
+ }
+ }
+ }
+ }
+ }
+
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ synchronized (mQueueLock) {
+ int N = mBackupParticipants.size();
+ pw.println("Participants:");
+ for (int i=0; i<N; i++) {
+ int uid = mBackupParticipants.keyAt(i);
+ pw.print(" uid: ");
+ pw.println(uid);
+ HashSet<ServiceInfo> services = mBackupParticipants.valueAt(i);
+ for (ServiceInfo s: services) {
+ pw.print(" ");
+ pw.println(s.toString());
+ }
+ }
+ }
+ }
+}
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index 73ff501..90d8c9d 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -84,7 +84,7 @@
private static final int CRITICAL_BATTERY_LEVEL = 4;
private static final int DUMP_MAX_LENGTH = 24 * 1024;
- private static final String[] DUMPSYS_ARGS = new String[] { "-c", "-u" };
+ private static final String[] DUMPSYS_ARGS = new String[] { "--checkin", "-u" };
private static final String BATTERY_STATS_SERVICE_NAME = "batteryinfo";
private static final String DUMPSYS_DATA_PATH = "/data/system/";
@@ -229,6 +229,16 @@
EventLog.writeEvent(LOG_BATTERY_LEVEL,
mBatteryLevel, mBatteryVoltage, mBatteryTemperature);
}
+ if (mBatteryLevel != mLastBatteryLevel && mPlugType == BATTERY_PLUGGED_NONE) {
+ // If the battery level has changed and we are on battery, update the current level.
+ // This is used for discharge cycle tracking so this shouldn't be updated while the
+ // battery is charging.
+ try {
+ mBatteryStats.recordCurrentLevel(mBatteryLevel);
+ } catch (RemoteException e) {
+ // Should never happen.
+ }
+ }
if (mBatteryLevelCritical && !mLastBatteryLevelCritical &&
mPlugType == BATTERY_PLUGGED_NONE) {
// We want to make sure we log discharge cycle outliers
@@ -237,6 +247,20 @@
logOutlier = true;
}
+ // Separate broadcast is sent for power connected / not connected
+ // since the standard intent will not wake any applications and some
+ // applications may want to have smart behavior based on this.
+ if (mPlugType != 0 && mLastPlugType == 0) {
+ Intent intent = new Intent(Intent.ACTION_POWER_CONNECTED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ mContext.sendBroadcast(intent);
+ }
+ else if (mPlugType == 0 && mLastPlugType != 0) {
+ Intent intent = new Intent(Intent.ACTION_POWER_DISCONNECTED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ mContext.sendBroadcast(intent);
+ }
+
mLastBatteryStatus = mBatteryStatus;
mLastBatteryHealth = mBatteryHealth;
mLastBatteryPresent = mBatteryPresent;
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 760988d..493bd09 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -35,7 +35,6 @@
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.provider.Settings;
-import android.provider.Sync;
import android.util.EventLog;
import android.util.Log;
diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java
index 85861bb..52e09ca 100644
--- a/services/java/com/android/server/DeviceStorageMonitorService.java
+++ b/services/java/com/android/server/DeviceStorageMonitorService.java
@@ -74,7 +74,7 @@
private boolean mLowMemFlag=false;
private Context mContext;
private ContentResolver mContentResolver;
- int mBlkSize;
+ long mBlkSize;
long mTotalMemory;
StatFs mFileStats;
private static final String DATA_PATH="/data";
@@ -251,7 +251,7 @@
//initialize block size
mBlkSize = mFileStats.getBlockSize();
//initialize total storage on device
- mTotalMemory = (mFileStats.getBlockCount()*mBlkSize)/100;
+ mTotalMemory = ((long)mFileStats.getBlockCount()*mBlkSize)/100L;
mStorageLowIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_LOW);
mStorageOkIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_OK);
checkMemory(true);
diff --git a/services/java/com/android/server/HeadsetObserver.java b/services/java/com/android/server/HeadsetObserver.java
index c9066be..3fc1e0e 100644
--- a/services/java/com/android/server/HeadsetObserver.java
+++ b/services/java/com/android/server/HeadsetObserver.java
@@ -21,6 +21,8 @@
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
import android.os.UEventObserver;
import android.util.Log;
import android.media.AudioManager;
@@ -38,15 +40,19 @@
private static final String HEADSET_STATE_PATH = "/sys/class/switch/h2w/state";
private static final String HEADSET_NAME_PATH = "/sys/class/switch/h2w/name";
- private Context mContext;
-
private int mHeadsetState;
private String mHeadsetName;
private boolean mAudioRouteNeedsUpdate;
private AudioManager mAudioManager;
+ private final Context mContext;
+ private final WakeLock mWakeLock; // held while there is a pending route change
+
public HeadsetObserver(Context context) {
mContext = context;
+ PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+ mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "HeadsetObserver");
+ mWakeLock.setReferenceCounted(false);
startObserving(HEADSET_UEVENT_MATCH);
@@ -103,6 +109,7 @@
// immediate, so delay the route change by 1000ms.
// This could be improved once the audio sub-system provides an
// interface to clear the audio pipeline.
+ mWakeLock.acquire();
mHandler.sendEmptyMessageDelayed(0, 1000);
} else {
updateAudioRoute();
@@ -138,7 +145,8 @@
@Override
public void handleMessage(Message msg) {
updateAudioRoute();
+ mWakeLock.release();
}
- };
+ };
}
diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java
index b534ef1..72efca5 100644
--- a/services/java/com/android/server/IntentResolver.java
+++ b/services/java/com/android/server/IntentResolver.java
@@ -16,6 +16,7 @@
package com.android.server;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -89,11 +90,11 @@
}
}
- void dumpMap(Printer out, String prefix, Map<String, ArrayList<F>> map) {
+ void dumpMap(PrintWriter out, String prefix, Map<String, ArrayList<F>> map) {
String eprefix = prefix + " ";
String fprefix = prefix + " ";
for (Map.Entry<String, ArrayList<F>> e : map.entrySet()) {
- out.println(eprefix + e.getKey() + ":");
+ out.print(eprefix); out.print(e.getKey()); out.println(":");
ArrayList<F> a = e.getValue();
final int N = a.size();
for (int i=0; i<N; i++) {
@@ -102,24 +103,25 @@
}
}
- public void dump(Printer out, String prefix) {
- out.println(prefix + "Full MIME Types:");
- dumpMap(out, prefix+" ", mTypeToFilter);
- out.println(prefix);
- out.println(prefix + "Base MIME Types:");
- dumpMap(out, prefix+" ", mBaseTypeToFilter);
- out.println(prefix);
- out.println(prefix + "Wild MIME Types:");
- dumpMap(out, prefix+" ", mWildTypeToFilter);
- out.println(prefix);
- out.println(prefix + "Schemes:");
- dumpMap(out, prefix+" ", mSchemeToFilter);
- out.println(prefix);
- out.println(prefix + "Non-Data Actions:");
- dumpMap(out, prefix+" ", mActionToFilter);
- out.println(prefix);
- out.println(prefix + "MIME Typed Actions:");
- dumpMap(out, prefix+" ", mTypedActionToFilter);
+ public void dump(PrintWriter out, String prefix) {
+ String innerPrefix = prefix + " ";
+ out.print(prefix); out.println("Full MIME Types:");
+ dumpMap(out, innerPrefix, mTypeToFilter);
+ out.println(" ");
+ out.print(prefix); out.println("Base MIME Types:");
+ dumpMap(out, innerPrefix, mBaseTypeToFilter);
+ out.println(" ");
+ out.print(prefix); out.println("Wild MIME Types:");
+ dumpMap(out, innerPrefix, mWildTypeToFilter);
+ out.println(" ");
+ out.print(prefix); out.println("Schemes:");
+ dumpMap(out, innerPrefix, mSchemeToFilter);
+ out.println(" ");
+ out.print(prefix); out.println("Non-Data Actions:");
+ dumpMap(out, innerPrefix, mActionToFilter);
+ out.println(" ");
+ out.print(prefix); out.println("MIME Typed Actions:");
+ dumpMap(out, innerPrefix, mTypedActionToFilter);
}
private class IteratorWrapper implements Iterator<F> {
@@ -275,8 +277,8 @@
Collections.sort(results, mResolvePrioritySorter);
}
- protected void dumpFilter(Printer out, String prefix, F filter) {
- out.println(prefix + filter);
+ protected void dumpFilter(PrintWriter out, String prefix, F filter) {
+ out.print(prefix); out.println(filter);
}
private final int register_mime_types(F filter, String prefix) {
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 705ddb3..05888e0 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -28,53 +28,52 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Observable;
+import java.util.Observer;
import java.util.Set;
import java.util.regex.Pattern;
-import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
+import android.content.ContentQueryMap;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.database.Cursor;
import android.location.Address;
+import android.location.IGeocodeProvider;
import android.location.IGpsStatusListener;
+import android.location.IGpsStatusProvider;
+import android.location.ILocationCollector;
import android.location.ILocationListener;
import android.location.ILocationManager;
+import android.location.ILocationProvider;
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationProvider;
-import android.location.LocationProviderImpl;
import android.net.ConnectivityManager;
import android.net.Uri;
-import android.net.wifi.ScanResult;
-import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.Settings;
-import android.telephony.CellLocation;
-import android.telephony.PhoneStateListener;
-import android.telephony.TelephonyManager;
import android.util.Config;
import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.SparseIntArray;
-import com.android.internal.app.IBatteryStats;
-import com.android.internal.location.CellState;
import com.android.internal.location.GpsLocationProvider;
-import com.android.internal.location.ILocationCollector;
-import com.android.internal.location.INetworkLocationManager;
-import com.android.internal.location.INetworkLocationProvider;
-import com.android.internal.location.TrackProvider;
+import com.android.internal.location.LocationProviderProxy;
+import com.android.internal.location.MockProvider;
import com.android.server.am.BatteryStatsService;
/**
@@ -83,8 +82,7 @@
*
* {@hide}
*/
-public class LocationManagerService extends ILocationManager.Stub
- implements INetworkLocationManager {
+public class LocationManagerService extends ILocationManager.Stub implements Runnable {
private static final String TAG = "LocationManagerService";
private static final boolean LOCAL_LOGV = false;
@@ -94,10 +92,6 @@
// Max time to hold wake lock for, in milliseconds.
private static final long MAX_TIME_FOR_WAKE_LOCK = 60 * 1000L;
- // Time to wait after releasing a wake lock for clients to process location update,
- // in milliseconds.
- private static final long TIME_AFTER_WAKE_LOCK = 2 * 1000L;
-
// The last time a location was written, by provider name.
private HashMap<String,Long> mLastWriteTime = new HashMap<String,Long>();
@@ -111,6 +105,10 @@
android.Manifest.permission.ACCESS_MOCK_LOCATION;
private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
+ private static final String INSTALL_LOCATION_PROVIDER =
+ android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
+ private static final String INSTALL_LOCATION_COLLECTOR =
+ android.Manifest.permission.INSTALL_LOCATION_COLLECTOR;
// Set of providers that are explicitly enabled
private final Set<String> mEnabledProviders = new HashSet<String>();
@@ -119,70 +117,41 @@
private final Set<String> mDisabledProviders = new HashSet<String>();
// Locations, status values, and extras for mock providers
- HashMap<String,MockProvider> mMockProviders = new HashMap<String,MockProvider>();
- private final HashMap<String,Location> mMockProviderLocation = new HashMap<String,Location>();
- private final HashMap<String,Integer> mMockProviderStatus = new HashMap<String,Integer>();
- private final HashMap<String,Bundle> mMockProviderStatusExtras = new HashMap<String,Bundle>();
- private final HashMap<String,Long> mMockProviderStatusUpdateTime = new HashMap<String,Long>();
+ private final HashMap<String,MockProvider> mMockProviders = new HashMap<String,MockProvider>();
private static boolean sProvidersLoaded = false;
private final Context mContext;
- private GpsLocationProvider mGpsLocationProvider;
- private boolean mGpsNavigating;
- private LocationProviderImpl mNetworkLocationProvider;
- private INetworkLocationProvider mNetworkLocationInterface;
+ private IGeocodeProvider mGeocodeProvider;
+ private IGpsStatusProvider mGpsStatusProvider;
private LocationWorkerHandler mLocationHandler;
// Handler messages
- private static final int MESSAGE_HEARTBEAT = 1;
- private static final int MESSAGE_ACQUIRE_WAKE_LOCK = 2;
- private static final int MESSAGE_RELEASE_WAKE_LOCK = 3;
- private static final int MESSAGE_INSTALL_NETWORK_LOCATION_PROVIDER = 4;
+ private static final int MESSAGE_LOCATION_CHANGED = 1;
- // Alarm manager and wakelock variables
- private final static String ALARM_INTENT = "com.android.location.ALARM_INTENT";
+ // wakelock variables
private final static String WAKELOCK_KEY = "LocationManagerService";
- private final static String WIFILOCK_KEY = "LocationManagerService";
- private AlarmManager mAlarmManager;
- private long mAlarmInterval = 0;
- private boolean mScreenOn = true;
private PowerManager.WakeLock mWakeLock = null;
- private WifiManager.WifiLock mWifiLock = null;
- private long mWakeLockAcquireTime = 0;
- private boolean mWakeLockGpsReceived = true;
- private boolean mWakeLockNetworkReceived = true;
- private boolean mWifiWakeLockAcquired = false;
- private boolean mCellWakeLockAcquired = false;
-
- private final IBatteryStats mBatteryStats;
+ private int mPendingBroadcasts;
/**
- * Mapping from listener IBinder/PendingIntent to local Listener wrappers.
+ * List of all receivers.
*/
- private final ArrayList<Receiver> mListeners = new ArrayList<Receiver>();
+ private final HashMap<Object, Receiver> mReceivers = new HashMap<Object, Receiver>();
+
/**
- * Used for reporting which UIDs are causing the GPS to run.
+ * List of location providers.
*/
- private final SparseIntArray mReportedGpsUids = new SparseIntArray();
- private int mReportedGpsSeq = 0;
-
- /**
- * Mapping from listener IBinder/PendingIntent to a map from provider name to UpdateRecord.
- * This also serves as the lock for our state.
- */
- private final HashMap<Receiver,HashMap<String,UpdateRecord>> mLocationListeners =
- new HashMap<Receiver,HashMap<String,UpdateRecord>>();
+ private final ArrayList<LocationProviderProxy> mProviders =
+ new ArrayList<LocationProviderProxy>();
+ private final HashMap<String, LocationProviderProxy> mProvidersByName
+ = new HashMap<String, LocationProviderProxy>();
/**
- * Mapping from listener IBinder/PendingIntent to a map from provider name to last broadcast
- * location.
+ * Object used internally for synchronization
*/
- private final HashMap<Receiver,HashMap<String,Location>> mLastFixBroadcast =
- new HashMap<Receiver,HashMap<String,Location>>();
- private final HashMap<Receiver,HashMap<String,Long>> mLastStatusBroadcast =
- new HashMap<Receiver,HashMap<String,Long>>();
+ private final Object mLock = new Object();
/**
* Mapping from provider name to all its UpdateRecords
@@ -190,15 +159,9 @@
private final HashMap<String,ArrayList<UpdateRecord>> mRecordsByProvider =
new HashMap<String,ArrayList<UpdateRecord>>();
- /**
- * Mappings from provider name to object to use for current location. Locations
- * contained in this list may not always be valid.
- */
- private final HashMap<String,Location> mLocationsByProvider =
- new HashMap<String,Location>();
-
// Proximity listeners
- private Receiver mProximityListener = null;
+ private Receiver mProximityReceiver = null;
+ private ILocationListener mProximityListener = null;
private HashMap<PendingIntent,ProximityAlert> mProximityAlerts =
new HashMap<PendingIntent,ProximityAlert>();
private HashSet<ProximityAlert> mProximitiesEntered =
@@ -208,44 +171,34 @@
private HashMap<String,Location> mLastKnownLocation =
new HashMap<String,Location>();
- // Battery status extras (from com.android.server.BatteryService)
- private static final String BATTERY_EXTRA_SCALE = "scale";
- private static final String BATTERY_EXTRA_LEVEL = "level";
- private static final String BATTERY_EXTRA_PLUGGED = "plugged";
-
- // Last known cell service state
- private TelephonyManager mTelephonyManager;
-
// Location collector
private ILocationCollector mCollector;
- // Wifi Manager
- private WifiManager mWifiManager;
-
private int mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
- private boolean mWifiEnabled = false;
+
+ // for Settings change notification
+ private ContentQueryMap mSettings;
/**
* A wrapper class holding either an ILocationListener or a PendingIntent to receive
* location updates.
*/
- private final class Receiver implements IBinder.DeathRecipient {
+ private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
final ILocationListener mListener;
final PendingIntent mPendingIntent;
- final int mUid;
final Object mKey;
+ final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
+ int mPendingBroadcasts;
- Receiver(ILocationListener listener, int uid) {
+ Receiver(ILocationListener listener) {
mListener = listener;
mPendingIntent = null;
- mUid = uid;
mKey = listener.asBinder();
}
- Receiver(PendingIntent intent, int uid) {
+ Receiver(PendingIntent intent) {
mPendingIntent = intent;
mListener = null;
- mUid = uid;
mKey = intent;
}
@@ -262,18 +215,17 @@
public int hashCode() {
return mKey.hashCode();
}
-
-
+
@Override
public String toString() {
if (mListener != null) {
return "Receiver{"
+ Integer.toHexString(System.identityHashCode(this))
- + " uid " + mUid + " Listener " + mKey + "}";
+ + " Listener " + mKey + "}";
} else {
return "Receiver{"
+ Integer.toHexString(System.identityHashCode(this))
- + " uid " + mUid + " Intent " + mKey + "}";
+ + " Intent " + mKey + "}";
}
}
@@ -302,7 +254,16 @@
public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
if (mListener != null) {
try {
- mListener.onStatusChanged(provider, status, extras);
+ synchronized (this) {
+ // synchronize to ensure incrementPendingBroadcastsLocked()
+ // is called before decrementPendingBroadcasts()
+ mListener.onStatusChanged(provider, status, extras);
+ if (mListener != mProximityListener) {
+ // call this after broadcasting so we do not increment
+ // if we throw an exeption.
+ incrementPendingBroadcastsLocked();
+ }
+ }
} catch (RemoteException e) {
return false;
}
@@ -311,7 +272,14 @@
statusChanged.putExtras(extras);
statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
try {
- mPendingIntent.send(mContext, 0, statusChanged, null, null);
+ synchronized (this) {
+ // synchronize to ensure incrementPendingBroadcastsLocked()
+ // is called before decrementPendingBroadcasts()
+ mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler);
+ // call this after broadcasting so we do not increment
+ // if we throw an exeption.
+ incrementPendingBroadcastsLocked();
+ }
} catch (PendingIntent.CanceledException e) {
return false;
}
@@ -322,7 +290,16 @@
public boolean callLocationChangedLocked(Location location) {
if (mListener != null) {
try {
- mListener.onLocationChanged(location);
+ synchronized (this) {
+ // synchronize to ensure incrementPendingBroadcastsLocked()
+ // is called before decrementPendingBroadcasts()
+ mListener.onLocationChanged(location);
+ if (mListener != mProximityListener) {
+ // call this after broadcasting so we do not increment
+ // if we throw an exeption.
+ incrementPendingBroadcastsLocked();
+ }
+ }
} catch (RemoteException e) {
return false;
}
@@ -330,7 +307,53 @@
Intent locationChanged = new Intent();
locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, location);
try {
- mPendingIntent.send(mContext, 0, locationChanged, null, null);
+ synchronized (this) {
+ // synchronize to ensure incrementPendingBroadcastsLocked()
+ // is called before decrementPendingBroadcasts()
+ mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler);
+ // call this after broadcasting so we do not increment
+ // if we throw an exeption.
+ incrementPendingBroadcastsLocked();
+ }
+ } catch (PendingIntent.CanceledException e) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean callProviderEnabledLocked(String provider, boolean enabled) {
+ if (mListener != null) {
+ try {
+ synchronized (this) {
+ // synchronize to ensure incrementPendingBroadcastsLocked()
+ // is called before decrementPendingBroadcasts()
+ if (enabled) {
+ mListener.onProviderEnabled(provider);
+ } else {
+ mListener.onProviderDisabled(provider);
+ }
+ if (mListener != mProximityListener) {
+ // call this after broadcasting so we do not increment
+ // if we throw an exeption.
+ incrementPendingBroadcastsLocked();
+ }
+ }
+ } catch (RemoteException e) {
+ return false;
+ }
+ } else {
+ Intent providerIntent = new Intent();
+ providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
+ try {
+ synchronized (this) {
+ // synchronize to ensure incrementPendingBroadcastsLocked()
+ // is called before decrementPendingBroadcasts()
+ mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler);
+ // call this after broadcasting so we do not increment
+ // if we throw an exeption.
+ incrementPendingBroadcastsLocked();
+ }
} catch (PendingIntent.CanceledException e) {
return false;
}
@@ -342,9 +365,56 @@
if (LOCAL_LOGV) {
Log.v(TAG, "Location listener died");
}
- synchronized (mLocationListeners) {
+ synchronized (mLock) {
removeUpdatesLocked(this);
}
+ synchronized (this) {
+ if (mPendingBroadcasts > 0) {
+ LocationManagerService.this.decrementPendingBroadcasts();
+ mPendingBroadcasts = 0;
+ }
+ }
+ }
+
+ public void onSendFinished(PendingIntent pendingIntent, Intent intent,
+ int resultCode, String resultData, Bundle resultExtras) {
+ synchronized (this) {
+ decrementPendingBroadcastsLocked();
+ }
+ }
+
+ // this must be called while synchronized by caller in a synchronized block
+ // containing the sending of the broadcaset
+ private void incrementPendingBroadcastsLocked() {
+ if (mPendingBroadcasts++ == 0) {
+ LocationManagerService.this.incrementPendingBroadcasts();
+ }
+ }
+
+ private void decrementPendingBroadcastsLocked() {
+ if (--mPendingBroadcasts == 0) {
+ LocationManagerService.this.decrementPendingBroadcasts();
+ }
+ }
+ }
+
+ public void locationCallbackFinished(ILocationListener listener) {
+ Receiver receiver = getReceiver(listener);
+ if (receiver != null) {
+ synchronized (receiver) {
+ // so wakelock calls will succeed
+ long identity = Binder.clearCallingIdentity();
+ receiver.decrementPendingBroadcastsLocked();
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
+ private final class SettingsObserver implements Observer {
+ public void update(Observable o, Object arg) {
+ synchronized (mLock) {
+ updateProvidersLocked();
+ }
}
}
@@ -439,17 +509,18 @@
}
}
- /**
- * Load providers from /data/location/<provider_name>/
- * class
- * kml
- * nmea
- * track
- * location
- * properties
- */
+ private void addProvider(LocationProviderProxy provider) {
+ mProviders.add(provider);
+ mProvidersByName.put(provider.getName(), provider);
+ }
+
+ private void removeProvider(LocationProviderProxy provider) {
+ mProviders.remove(provider);
+ mProvidersByName.remove(provider.getName());
+ }
+
private void loadProviders() {
- synchronized (mLocationListeners) {
+ synchronized (mLock) {
if (sProvidersLoaded) {
return;
}
@@ -472,73 +543,10 @@
// Attempt to load "real" providers first
if (GpsLocationProvider.isSupported()) {
// Create a gps location provider
- mGpsLocationProvider = new GpsLocationProvider(mContext);
- LocationProviderImpl.addProvider(mGpsLocationProvider);
- }
-
- // Load fake providers if real providers are not available
- File f = new File(LocationManager.PROVIDER_DIR);
- if (f.isDirectory()) {
- File[] subdirs = f.listFiles();
- for (int i = 0; i < subdirs.length; i++) {
- if (!subdirs[i].isDirectory()) {
- continue;
- }
-
- String name = subdirs[i].getName();
-
- if (LOCAL_LOGV) {
- Log.v(TAG, "Found dir " + subdirs[i].getAbsolutePath());
- Log.v(TAG, "name = " + name);
- }
-
- // Don't create a fake provider if a real provider exists
- if (LocationProviderImpl.getProvider(name) == null) {
- LocationProviderImpl provider = null;
- try {
- File classFile = new File(subdirs[i], "class");
- // Look for a 'class' file
- provider = LocationProviderImpl.loadFromClass(classFile);
-
- // Look for an 'kml', 'nmea', or 'track' file
- if (provider == null) {
- // Load properties from 'properties' file, if present
- File propertiesFile = new File(subdirs[i], "properties");
-
- if (propertiesFile.exists()) {
- provider = new TrackProvider(name);
- ((TrackProvider)provider).readProperties(propertiesFile);
-
- File kmlFile = new File(subdirs[i], "kml");
- if (kmlFile.exists()) {
- ((TrackProvider) provider).readKml(kmlFile);
- } else {
- File nmeaFile = new File(subdirs[i], "nmea");
- if (nmeaFile.exists()) {
- ((TrackProvider) provider).readNmea(name, nmeaFile);
- } else {
- File trackFile = new File(subdirs[i], "track");
- if (trackFile.exists()) {
- ((TrackProvider) provider).readTrack(trackFile);
- }
- }
- }
- }
- }
- if (provider != null) {
- LocationProviderImpl.addProvider(provider);
- }
- // Grab the initial location of a TrackProvider and
- // store it as the last known location for that provider
- if (provider instanceof TrackProvider) {
- TrackProvider tp = (TrackProvider) provider;
- mLastKnownLocation.put(tp.getName(), tp.getInitialLocation());
- }
- } catch (Exception e) {
- Log.e(TAG, "Exception loading provder " + name, e);
- }
- }
- }
+ GpsLocationProvider provider = new GpsLocationProvider(mContext, this);
+ mGpsStatusProvider = provider.getGpsStatusProvider();
+ LocationProviderProxy proxy = new LocationProviderProxy(LocationManager.GPS_PROVIDER, provider);
+ addProvider(proxy);
}
updateProvidersLocked();
@@ -550,118 +558,95 @@
public LocationManagerService(Context context) {
super();
mContext = context;
- mLocationHandler = new LocationWorkerHandler();
+
+ Thread thread = new Thread(null, this, "LocationManagerService");
+ thread.start();
if (LOCAL_LOGV) {
Log.v(TAG, "Constructed LocationManager Service");
}
+ }
- // Alarm manager, needs to be done before calling loadProviders() below
- mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
-
+ private void initialize() {
// Create a wake lock, needs to be done before calling loadProviders() below
PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
-
- // Battery statistics service to be notified when GPS turns on or off
- mBatteryStats = BatteryStatsService.getService();
// Load providers
loadProviders();
- // Listen for Radio changes
- mTelephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
- mTelephonyManager.listen(mPhoneStateListener,
- PhoneStateListener.LISTEN_CELL_LOCATION |
- PhoneStateListener.LISTEN_SIGNAL_STRENGTH |
- PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
-
// Register for Network (Wifi or Mobile) updates
- NetworkStateBroadcastReceiver networkReceiver = new NetworkStateBroadcastReceiver();
- IntentFilter networkIntentFilter = new IntentFilter();
- networkIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
- networkIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
- networkIntentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
- networkIntentFilter.addAction(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION);
- context.registerReceiver(networkReceiver, networkIntentFilter);
-
- // Register for power updates
- PowerStateBroadcastReceiver powerStateReceiver = new PowerStateBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(ALARM_INTENT);
- intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
- intentFilter.addAction(Intent.ACTION_SCREEN_ON);
- intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
+ intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ // Register for Package Manager updates
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
- context.registerReceiver(powerStateReceiver, intentFilter);
+ mContext.registerReceiver(mBroadcastReceiver, intentFilter);
- // Get the wifi manager
- mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
-
- // Create a wifi lock for future use
- mWifiLock = getWifiWakelockLocked();
+ // listen for settings changes
+ ContentResolver resolver = mContext.getContentResolver();
+ Cursor settingsCursor = resolver.query(Settings.Secure.CONTENT_URI, null,
+ "(" + Settings.System.NAME + "=?)",
+ new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
+ null);
+ mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mLocationHandler);
+ SettingsObserver settingsObserver = new SettingsObserver();
+ mSettings.addObserver(settingsObserver);
}
- public void setInstallCallback(InstallCallback callback) {
- synchronized (mLocationListeners) {
- mLocationHandler.removeMessages(MESSAGE_INSTALL_NETWORK_LOCATION_PROVIDER);
- Message m = Message.obtain(mLocationHandler,
- MESSAGE_INSTALL_NETWORK_LOCATION_PROVIDER, callback);
- mLocationHandler.sendMessageAtFrontOfQueue(m);
+ public void run()
+ {
+ Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+ Looper.prepare();
+ mLocationHandler = new LocationWorkerHandler();
+ initialize();
+ Looper.loop();
+ }
+
+ public void installLocationProvider(String name, ILocationProvider provider) {
+ if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");
}
- }
- public void setNetworkLocationProvider(INetworkLocationProvider provider) {
- synchronized (mLocationListeners) {
- mNetworkLocationInterface = provider;
- provider.addListener(getPackageNames());
- mNetworkLocationProvider = (LocationProviderImpl)provider;
- LocationProviderImpl.addProvider(mNetworkLocationProvider);
+ synchronized (mLock) {
+ // check to see if we are reinstalling a dead provider
+ LocationProviderProxy oldProvider = mProvidersByName.get(name);
+ if (oldProvider != null) {
+ if (oldProvider.isDead()) {
+ Log.d(TAG, "replacing dead provider");
+ removeProvider(oldProvider);
+ } else {
+ throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
+ }
+ }
+
+ LocationProviderProxy proxy = new LocationProviderProxy(name, provider);
+ addProvider(proxy);
updateProvidersLocked();
-
- // notify NetworkLocationProvider of any events it might have missed
- synchronized (mLocationListeners) {
- mNetworkLocationProvider.updateNetworkState(mNetworkState);
- mNetworkLocationInterface.updateWifiEnabledState(mWifiEnabled);
- mNetworkLocationInterface.updateCellLockStatus(mCellWakeLockAcquired);
- if (mLastCellState != null) {
- if (mCollector != null) {
- mCollector.updateCellState(mLastCellState);
- }
- mNetworkLocationProvider.updateCellState(mLastCellState);
- }
-
- // There might be an existing wifi scan available
- if (mWifiManager != null) {
- List<ScanResult> wifiScanResults = mWifiManager.getScanResults();
- if (wifiScanResults != null && wifiScanResults.size() != 0) {
- mNetworkLocationInterface.updateWifiScanResults(wifiScanResults);
- if (mCollector != null) {
- mCollector.updateWifiScanResults(wifiScanResults);
- }
- }
- }
- }
+ // notify provider of current network state
+ proxy.updateNetworkState(mNetworkState);
}
}
- public void setLocationCollector(ILocationCollector collector) {
- synchronized (mLocationListeners) {
- mCollector = collector;
- if (mGpsLocationProvider != null) {
- mGpsLocationProvider.setLocationCollector(mCollector);
- }
+ public void installLocationCollector(ILocationCollector collector) {
+ if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_COLLECTOR)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires INSTALL_LOCATION_COLLECTOR permission");
}
+
+ // FIXME - only support one collector
+ mCollector = collector;
}
- private WifiManager.WifiLock getWifiWakelockLocked() {
- if (mWifiLock == null && mWifiManager != null) {
- mWifiLock = mWifiManager.createWifiLock(WifiManager.WIFI_MODE_SCAN_ONLY, WIFILOCK_KEY);
- mWifiLock.setReferenceCounted(false);
+ public void installGeocodeProvider(IGeocodeProvider provider) {
+ if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");
}
- return mWifiLock;
+
+ mGeocodeProvider = provider;
}
private boolean isAllowedBySettingsLocked(String provider) {
@@ -712,15 +697,9 @@
return true;
}
- private String[] getPackageNames() {
- // Since a single UID may correspond to multiple packages, this can only be used as an
- // approximation for tracking
- return mContext.getPackageManager().getPackagesForUid(Binder.getCallingUid());
- }
-
public List<String> getAllProviders() {
try {
- synchronized (mLocationListeners) {
+ synchronized (mLock) {
return _getAllProvidersLocked();
}
} catch (SecurityException se) {
@@ -735,10 +714,9 @@
if (LOCAL_LOGV) {
Log.v(TAG, "getAllProviders");
}
- List<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
- ArrayList<String> out = new ArrayList<String>(providers.size());
-
- for (LocationProviderImpl p : providers) {
+ ArrayList<String> out = new ArrayList<String>(mProviders.size());
+ for (int i = mProviders.size() - 1; i >= 0; i--) {
+ LocationProviderProxy p = mProviders.get(i);
out.add(p.getName());
}
return out;
@@ -746,7 +724,7 @@
public List<String> getProviders(boolean enabledOnly) {
try {
- synchronized (mLocationListeners) {
+ synchronized (mLock) {
return _getProvidersLocked(enabledOnly);
}
} catch (SecurityException se) {
@@ -761,10 +739,9 @@
if (LOCAL_LOGV) {
Log.v(TAG, "getProviders");
}
- List<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
- ArrayList<String> out = new ArrayList<String>();
-
- for (LocationProviderImpl p : providers) {
+ ArrayList<String> out = new ArrayList<String>(mProviders.size());
+ for (int i = mProviders.size() - 1; i >= 0; i--) {
+ LocationProviderProxy p = mProviders.get(i);
String name = p.getName();
if (isAllowedProviderSafe(name)) {
if (enabledOnly && !isAllowedBySettingsLocked(name)) {
@@ -776,24 +753,13 @@
return out;
}
- public void updateProviders() {
- synchronized (mLocationListeners) {
- updateProvidersLocked();
- }
- }
-
private void updateProvidersLocked() {
- for (LocationProviderImpl p : LocationProviderImpl.getProviders()) {
+ for (int i = mProviders.size() - 1; i >= 0; i--) {
+ LocationProviderProxy p = mProviders.get(i);
boolean isEnabled = p.isEnabled();
String name = p.getName();
boolean shouldBeEnabled = isAllowedBySettingsLocked(name);
- // Collection is only allowed when network provider is being used
- if (mCollector != null &&
- p.getName().equals(LocationManager.NETWORK_PROVIDER)) {
- mCollector.updateNetworkProviderStatus(shouldBeEnabled);
- }
-
if (isEnabled && !shouldBeEnabled) {
updateProviderListenersLocked(name, false);
} else if (!isEnabled && shouldBeEnabled) {
@@ -806,7 +772,7 @@
private void updateProviderListenersLocked(String provider, boolean enabled) {
int listeners = 0;
- LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
+ LocationProviderProxy p = mProvidersByName.get(provider);
if (p == null) {
return;
}
@@ -819,29 +785,11 @@
for (int i=0; i<N; i++) {
UpdateRecord record = records.get(i);
// Sends a notification message to the receiver
- try {
- Receiver receiver = record.mReceiver;
- if (receiver.isListener()) {
- if (enabled) {
- receiver.getListener().onProviderEnabled(provider);
- } else {
- receiver.getListener().onProviderDisabled(provider);
- }
- } else {
- Intent providerIntent = new Intent();
- providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
- try {
- receiver.getPendingIntent().send(mContext, 0,
- providerIntent, null, null);
- } catch (PendingIntent.CanceledException e) {
- if (deadReceivers == null) {
- deadReceivers = new ArrayList<Receiver>();
- deadReceivers.add(receiver);
- }
- }
+ if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
+ if (deadReceivers == null) {
+ deadReceivers = new ArrayList<Receiver>();
+ deadReceivers.add(record.mReceiver);
}
- } catch (RemoteException e) {
- // The death link will clean this up.
}
listeners++;
}
@@ -858,24 +806,10 @@
if (listeners > 0) {
p.setMinTime(getMinTimeLocked(provider));
p.enableLocationTracking(true);
- updateWakelockStatusLocked(mScreenOn);
}
} else {
p.enableLocationTracking(false);
- if (p == mGpsLocationProvider) {
- mGpsNavigating = false;
- reportStopGpsLocked();
- }
p.disable();
- updateWakelockStatusLocked(mScreenOn);
- }
-
- if (enabled && listeners > 0) {
- mLocationHandler.removeMessages(MESSAGE_HEARTBEAT, provider);
- Message m = Message.obtain(mLocationHandler, MESSAGE_HEARTBEAT, provider);
- mLocationHandler.sendMessageAtTime(m, SystemClock.uptimeMillis() + 1000);
- } else {
- mLocationHandler.removeMessages(MESSAGE_HEARTBEAT, provider);
}
}
@@ -896,19 +830,19 @@
final long mMinTime;
final float mMinDistance;
final int mUid;
- final String[] mPackages;
+ Location mLastFixBroadcast;
+ long mLastStatusBroadcast;
/**
* Note: must be constructed with lock held.
*/
UpdateRecord(String provider, long minTime, float minDistance,
- Receiver receiver, int uid, String[] packages) {
+ Receiver receiver, int uid) {
mProvider = provider;
mReceiver = receiver;
mMinTime = minTime;
mMinDistance = minDistance;
mUid = uid;
- mPackages = packages;
ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
if (records == null) {
@@ -940,33 +874,74 @@
pw.println(prefix + this);
pw.println(prefix + "mProvider=" + mProvider + " mReceiver=" + mReceiver);
pw.println(prefix + "mMinTime=" + mMinTime + " mMinDistance=" + mMinDistance);
- StringBuilder sb = new StringBuilder();
- if (mPackages != null) {
- for (int i=0; i<mPackages.length; i++) {
- if (i > 0) sb.append(", ");
- sb.append(mPackages[i]);
- }
- }
- pw.println(prefix + "mUid=" + mUid + " mPackages=" + sb);
+ pw.println(prefix + "mUid=" + mUid);
+ pw.println(prefix + "mLastFixBroadcast:");
+ mLastFixBroadcast.dump(new PrintWriterPrinter(pw), prefix + " ");
+ pw.println(prefix + "mLastStatusBroadcast=" + mLastStatusBroadcast);
}
/**
* Calls dispose().
*/
@Override protected void finalize() {
- synchronized (mLocationListeners) {
+ synchronized (mLock) {
disposeLocked();
}
}
}
+ private Receiver getReceiver(ILocationListener listener) {
+ IBinder binder = listener.asBinder();
+ Receiver receiver = mReceivers.get(binder);
+ if (receiver == null) {
+ receiver = new Receiver(listener);
+ mReceivers.put(binder, receiver);
+
+ try {
+ if (receiver.isListener()) {
+ receiver.getListener().asBinder().linkToDeath(receiver, 0);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "linkToDeath failed:", e);
+ return null;
+ }
+ }
+ return receiver;
+ }
+
+ private Receiver getReceiver(PendingIntent intent) {
+ Receiver receiver = mReceivers.get(intent);
+ if (receiver == null) {
+ receiver = new Receiver(intent);
+ mReceivers.put(intent, receiver);
+ }
+ return receiver;
+ }
+
+ private boolean providerHasListener(String provider, int uid, Receiver excludedReceiver) {
+ ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
+ if (records != null) {
+ for (int i = records.size() - 1; i >= 0; i--) {
+ UpdateRecord record = records.get(i);
+ if (record.mUid == uid && record.mReceiver != excludedReceiver) {
+ return true;
+ }
+ }
+ }
+ for (ProximityAlert alert : mProximityAlerts.values()) {
+ if (alert.mUid == uid) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public void requestLocationUpdates(String provider,
long minTime, float minDistance, ILocationListener listener) {
try {
- synchronized (mLocationListeners) {
- requestLocationUpdatesLocked(provider, minTime, minDistance,
- new Receiver(listener, Binder.getCallingUid()));
+ synchronized (mLock) {
+ requestLocationUpdatesLocked(provider, minTime, minDistance, getReceiver(listener));
}
} catch (SecurityException se) {
throw se;
@@ -978,9 +953,8 @@
public void requestLocationUpdatesPI(String provider,
long minTime, float minDistance, PendingIntent intent) {
try {
- synchronized (mLocationListeners) {
- requestLocationUpdatesLocked(provider, minTime, minDistance,
- new Receiver(intent, Binder.getCallingUid()));
+ synchronized (mLock) {
+ requestLocationUpdatesLocked(provider, minTime, minDistance, getReceiver(intent));
}
} catch (SecurityException se) {
throw se;
@@ -995,69 +969,36 @@
Log.v(TAG, "_requestLocationUpdates: listener = " + receiver);
}
- LocationProviderImpl impl = LocationProviderImpl.getProvider(provider);
- if (impl == null) {
+ LocationProviderProxy proxy = mProvidersByName.get(provider);
+ if (proxy == null) {
throw new IllegalArgumentException("provider=" + provider);
}
checkPermissionsSafe(provider);
- String[] packages = getPackageNames();
-
// so wakelock calls will succeed
final int callingUid = Binder.getCallingUid();
+ boolean newUid = !providerHasListener(provider, callingUid, null);
long identity = Binder.clearCallingIdentity();
try {
- UpdateRecord r = new UpdateRecord(provider, minTime, minDistance,
- receiver, callingUid, packages);
- if (!mListeners.contains(receiver)) {
- try {
- if (receiver.isListener()) {
- receiver.getListener().asBinder().linkToDeath(receiver, 0);
- }
- mListeners.add(receiver);
- } catch (RemoteException e) {
- return;
- }
- }
-
- HashMap<String,UpdateRecord> records = mLocationListeners.get(receiver);
- if (records == null) {
- records = new HashMap<String,UpdateRecord>();
- mLocationListeners.put(receiver, records);
- }
- UpdateRecord oldRecord = records.put(provider, r);
+ UpdateRecord r = new UpdateRecord(provider, minTime, minDistance, receiver, callingUid);
+ UpdateRecord oldRecord = receiver.mUpdateRecords.put(provider, r);
if (oldRecord != null) {
oldRecord.disposeLocked();
}
+ if (newUid) {
+ proxy.addListener(callingUid);
+ }
+
boolean isProviderEnabled = isAllowedBySettingsLocked(provider);
if (isProviderEnabled) {
long minTimeForProvider = getMinTimeLocked(provider);
- impl.setMinTime(minTimeForProvider);
- impl.enableLocationTracking(true);
- updateWakelockStatusLocked(mScreenOn);
-
- if (provider.equals(LocationManager.GPS_PROVIDER)) {
- if (mGpsNavigating) {
- updateReportedGpsLocked();
- }
- }
-
- // Clear heartbeats if any before starting a new one
- mLocationHandler.removeMessages(MESSAGE_HEARTBEAT, provider);
- Message m = Message.obtain(mLocationHandler, MESSAGE_HEARTBEAT, provider);
- mLocationHandler.sendMessageAtTime(m, SystemClock.uptimeMillis() + 1000);
+ proxy.setMinTime(minTimeForProvider);
+ proxy.enableLocationTracking(true);
} else {
- try {
- // Notify the listener that updates are currently disabled
- if (receiver.isListener()) {
- receiver.getListener().onProviderDisabled(provider);
- }
- } catch(RemoteException e) {
- Log.w(TAG, "RemoteException calling onProviderDisabled on " +
- receiver.getListener());
- }
+ // Notify the listener that updates are currently disabled
+ receiver.callProviderEnabledLocked(provider, false);
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -1066,8 +1007,8 @@
public void removeUpdates(ILocationListener listener) {
try {
- synchronized (mLocationListeners) {
- removeUpdatesLocked(new Receiver(listener, Binder.getCallingUid()));
+ synchronized (mLock) {
+ removeUpdatesLocked(getReceiver(listener));
}
} catch (SecurityException se) {
throw se;
@@ -1078,8 +1019,8 @@
public void removeUpdatesPI(PendingIntent intent) {
try {
- synchronized (mLocationListeners) {
- removeUpdatesLocked(new Receiver(intent, Binder.getCallingUid()));
+ synchronized (mLock) {
+ removeUpdatesLocked(getReceiver(intent));
}
} catch (SecurityException se) {
throw se;
@@ -1097,23 +1038,20 @@
final int callingUid = Binder.getCallingUid();
long identity = Binder.clearCallingIdentity();
try {
- int idx = mListeners.indexOf(receiver);
- if (idx >= 0) {
- Receiver myReceiver = mListeners.remove(idx);
- if (myReceiver.isListener()) {
- myReceiver.getListener().asBinder().unlinkToDeath(myReceiver, 0);
- }
+ if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
+ receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
}
// Record which providers were associated with this listener
HashSet<String> providers = new HashSet<String>();
- HashMap<String,UpdateRecord> oldRecords = mLocationListeners.get(receiver);
+ HashMap<String,UpdateRecord> oldRecords = receiver.mUpdateRecords;
if (oldRecords != null) {
// Call dispose() on the obsolete update records.
for (UpdateRecord record : oldRecords.values()) {
- if (record.mProvider.equals(LocationManager.NETWORK_PROVIDER)) {
- if (mNetworkLocationInterface != null) {
- mNetworkLocationInterface.removeListener(record.mPackages);
+ if (!providerHasListener(record.mProvider, callingUid, receiver)) {
+ LocationProviderProxy proxy = mProvidersByName.get(record.mProvider);
+ if (proxy != null) {
+ proxy.removeListener(callingUid);
}
}
record.disposeLocked();
@@ -1121,10 +1059,6 @@
// Accumulate providers
providers.addAll(oldRecords.keySet());
}
-
- mLocationListeners.remove(receiver);
- mLastFixBroadcast.remove(receiver);
- mLastStatusBroadcast.remove(receiver);
// See if the providers associated with this listener have any
// other listeners; if one does, inform it of the new smallest minTime
@@ -1141,29 +1075,22 @@
hasOtherListener = true;
}
- LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
+ LocationProviderProxy p = mProvidersByName.get(provider);
if (p != null) {
if (hasOtherListener) {
p.setMinTime(getMinTimeLocked(provider));
} else {
- mLocationHandler.removeMessages(MESSAGE_HEARTBEAT, provider);
p.enableLocationTracking(false);
}
-
- if (p == mGpsLocationProvider && mGpsNavigating) {
- updateReportedGpsLocked();
- }
}
}
-
- updateWakelockStatusLocked(mScreenOn);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
public boolean addGpsStatusListener(IGpsStatusListener listener) {
- if (mGpsLocationProvider == null) {
+ if (mGpsStatusProvider == null) {
return false;
}
if (mContext.checkCallingPermission(ACCESS_FINE_LOCATION) !=
@@ -1172,17 +1099,21 @@
}
try {
- mGpsLocationProvider.addGpsStatusListener(listener);
+ mGpsStatusProvider.addGpsStatusListener(listener);
} catch (RemoteException e) {
- Log.w(TAG, "RemoteException in addGpsStatusListener");
+ Log.e(TAG, "mGpsStatusProvider.addGpsStatusListener failed", e);
return false;
}
return true;
}
public void removeGpsStatusListener(IGpsStatusListener listener) {
- synchronized (mLocationListeners) {
- mGpsLocationProvider.removeGpsStatusListener(listener);
+ synchronized (mLock) {
+ try {
+ mGpsStatusProvider.removeGpsStatusListener(listener);
+ } catch (Exception e) {
+ Log.e(TAG, "mGpsStatusProvider.removeGpsStatusListener failed", e);
+ }
}
}
@@ -1195,13 +1126,13 @@
throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
}
- synchronized (mLocationListeners) {
- LocationProviderImpl impl = LocationProviderImpl.getProvider(provider);
+ synchronized (mLock) {
+ LocationProviderProxy proxy = mProvidersByName.get(provider);
if (provider == null) {
return false;
}
- return impl.sendExtraCommand(command, extras);
+ return proxy.sendExtraCommand(command, extras);
}
}
@@ -1263,7 +1194,7 @@
}
// Listener for receiving locations to trigger proximity alerts
- class ProximityListener extends ILocationListener.Stub {
+ class ProximityListener extends ILocationListener.Stub implements PendingIntent.OnFinished {
boolean isGpsAvailable = false;
@@ -1300,7 +1231,14 @@
Intent enteredIntent = new Intent();
enteredIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, true);
try {
- intent.send(mContext, 0, enteredIntent, null, null);
+ synchronized (this) {
+ // synchronize to ensure incrementPendingBroadcasts()
+ // is called before decrementPendingBroadcasts()
+ intent.send(mContext, 0, enteredIntent, this, mLocationHandler);
+ // call this after broadcasting so we do not increment
+ // if we throw an exeption.
+ incrementPendingBroadcasts();
+ }
} catch (PendingIntent.CanceledException e) {
if (LOCAL_LOGV) {
Log.v(TAG, "Canceled proximity alert: " + alert, e);
@@ -1318,7 +1256,14 @@
Intent exitedIntent = new Intent();
exitedIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, false);
try {
- intent.send(mContext, 0, exitedIntent, null, null);
+ synchronized (this) {
+ // synchronize to ensure incrementPendingBroadcasts()
+ // is called before decrementPendingBroadcasts()
+ intent.send(mContext, 0, exitedIntent, this, mLocationHandler);
+ // call this after broadcasting so we do not increment
+ // if we throw an exeption.
+ incrementPendingBroadcasts();
+ }
} catch (PendingIntent.CanceledException e) {
if (LOCAL_LOGV) {
Log.v(TAG, "Canceled proximity alert: " + alert, e);
@@ -1371,12 +1316,21 @@
isGpsAvailable = false;
}
}
+
+ public void onSendFinished(PendingIntent pendingIntent, Intent intent,
+ int resultCode, String resultData, Bundle resultExtras) {
+ // synchronize to ensure incrementPendingBroadcasts()
+ // is called before decrementPendingBroadcasts()
+ synchronized (this) {
+ decrementPendingBroadcasts();
+ }
+ }
}
public void addProximityAlert(double latitude, double longitude,
float radius, long expiration, PendingIntent intent) {
try {
- synchronized (mLocationListeners) {
+ synchronized (mLock) {
addProximityAlertLocked(latitude, longitude, radius, expiration, intent);
}
} catch (SecurityException se) {
@@ -1408,28 +1362,20 @@
latitude, longitude, radius, expiration, intent);
mProximityAlerts.put(intent, alert);
- if (mProximityListener == null) {
- mProximityListener = new Receiver(new ProximityListener(), -1);
+ if (mProximityReceiver == null) {
+ mProximityListener = new ProximityListener();
+ mProximityReceiver = new Receiver(mProximityListener);
- LocationProvider provider = LocationProviderImpl.getProvider(
- LocationManager.GPS_PROVIDER);
- if (provider != null) {
- requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityListener);
+ for (int i = mProviders.size() - 1; i >= 0; i--) {
+ LocationProviderProxy provider = mProviders.get(i);
+ requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityReceiver);
}
-
- provider =
- LocationProviderImpl.getProvider(LocationManager.NETWORK_PROVIDER);
- if (provider != null) {
- requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityListener);
- }
- } else if (mGpsNavigating) {
- updateReportedGpsLocked();
}
}
public void removeProximityAlert(PendingIntent intent) {
try {
- synchronized (mLocationListeners) {
+ synchronized (mLock) {
removeProximityAlertLocked(intent);
}
} catch (SecurityException se) {
@@ -1446,10 +1392,9 @@
mProximityAlerts.remove(intent);
if (mProximityAlerts.size() == 0) {
- removeUpdatesLocked(mProximityListener);
+ removeUpdatesLocked(mProximityReceiver);
+ mProximityReceiver = null;
mProximityListener = null;
- } else if (mGpsNavigating) {
- updateReportedGpsLocked();
}
}
@@ -1460,7 +1405,7 @@
*/
public Bundle getProviderInfo(String provider) {
try {
- synchronized (mLocationListeners) {
+ synchronized (mLock) {
return _getProviderInfoLocked(provider);
}
} catch (SecurityException se) {
@@ -1472,7 +1417,7 @@
}
private Bundle _getProviderInfoLocked(String provider) {
- LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
+ LocationProviderProxy p = mProvidersByName.get(provider);
if (p == null) {
return null;
}
@@ -1495,7 +1440,7 @@
public boolean isProviderEnabled(String provider) {
try {
- synchronized (mLocationListeners) {
+ synchronized (mLock) {
return _isProviderEnabledLocked(provider);
}
} catch (SecurityException se) {
@@ -1506,10 +1451,21 @@
}
}
+ public void reportLocation(Location location) {
+ if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");
+ }
+
+ mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location);
+ Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location);
+ mLocationHandler.sendMessageAtFrontOfQueue(m);
+ }
+
private boolean _isProviderEnabledLocked(String provider) {
checkPermissionsSafe(provider);
- LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
+ LocationProviderProxy p = mProvidersByName.get(provider);
if (p == null) {
throw new IllegalArgumentException("provider=" + provider);
}
@@ -1518,7 +1474,7 @@
public Location getLastKnownLocation(String provider) {
try {
- synchronized (mLocationListeners) {
+ synchronized (mLock) {
return _getLastKnownLocationLocked(provider);
}
} catch (SecurityException se) {
@@ -1532,7 +1488,7 @@
private Location _getLastKnownLocationLocked(String provider) {
checkPermissionsSafe(provider);
- LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
+ LocationProviderProxy p = mProvidersByName.get(provider);
if (p == null) {
throw new IllegalArgumentException("provider=" + provider);
}
@@ -1576,79 +1532,34 @@
return true;
}
- private void handleLocationChangedLocked(String provider) {
+ private void handleLocationChangedLocked(Location location) {
+ String provider = location.getProvider();
ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
if (records == null || records.size() == 0) {
return;
}
- LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
+ LocationProviderProxy p = mProvidersByName.get(provider);
if (p == null) {
return;
}
- // Get location object
- Location loc = mLocationsByProvider.get(provider);
- if (loc == null) {
- loc = new Location(provider);
- mLocationsByProvider.put(provider, loc);
- } else {
- loc.reset();
- }
-
- // Use the mock location if available
- Location mockLoc = mMockProviderLocation.get(provider);
- boolean locationValid;
- if (mockLoc != null) {
- locationValid = true;
- loc.set(mockLoc);
- } else {
- locationValid = p.getLocation(loc);
- }
-
// Update last known location for provider
- if (locationValid) {
- Location location = mLastKnownLocation.get(provider);
- if (location == null) {
- mLastKnownLocation.put(provider, new Location(loc));
- } else {
- location.set(loc);
- }
- writeLastKnownLocationLocked(provider, loc);
-
- if (p instanceof INetworkLocationProvider) {
- mWakeLockNetworkReceived = true;
- } else if (p instanceof GpsLocationProvider) {
- // Gps location received signal is in NetworkStateBroadcastReceiver
- }
+ Location lastLocation = mLastKnownLocation.get(provider);
+ if (lastLocation == null) {
+ mLastKnownLocation.put(provider, new Location(location));
+ } else {
+ lastLocation.set(location);
}
+ writeLastKnownLocationLocked(provider, location);
// Fetch latest status update time
long newStatusUpdateTime = p.getStatusUpdateTime();
- // Override real time with mock time if present
- Long mockStatusUpdateTime = mMockProviderStatusUpdateTime.get(provider);
- if (mockStatusUpdateTime != null) {
- newStatusUpdateTime = mockStatusUpdateTime.longValue();
- }
-
- // Get latest status
+ // Get latest status
Bundle extras = new Bundle();
int status = p.getStatus(extras);
- // Override status with mock status if present
- Integer mockStatus = mMockProviderStatus.get(provider);
- if (mockStatus != null) {
- status = mockStatus.intValue();
- }
-
- // Override extras with mock extras if present
- Bundle mockExtras = mMockProviderStatusExtras.get(provider);
- if (mockExtras != null) {
- extras.clear();
- extras.putAll(mockExtras);
- }
-
ArrayList<Receiver> deadReceivers = null;
// Broadcast location or status to all listeners
@@ -1657,44 +1568,28 @@
UpdateRecord r = records.get(i);
Receiver receiver = r.mReceiver;
- // Broadcast location only if it is valid
- if (locationValid) {
- HashMap<String,Location> map = mLastFixBroadcast.get(receiver);
- if (map == null) {
- map = new HashMap<String,Location>();
- mLastFixBroadcast.put(receiver, map);
+ Location lastLoc = r.mLastFixBroadcast;
+ if ((lastLoc == null) || shouldBroadcastSafe(location, lastLoc, r)) {
+ if (lastLoc == null) {
+ lastLoc = new Location(location);
+ r.mLastFixBroadcast = lastLoc;
+ } else {
+ lastLoc.set(location);
}
- Location lastLoc = map.get(provider);
- if ((lastLoc == null) || shouldBroadcastSafe(loc, lastLoc, r)) {
- if (lastLoc == null) {
- lastLoc = new Location(loc);
- map.put(provider, lastLoc);
- } else {
- lastLoc.set(loc);
+ if (!receiver.callLocationChangedLocked(location)) {
+ Log.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
+ if (deadReceivers == null) {
+ deadReceivers = new ArrayList<Receiver>();
}
- if (!receiver.callLocationChangedLocked(loc)) {
- Log.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
- if (deadReceivers == null) {
- deadReceivers = new ArrayList<Receiver>();
- }
- deadReceivers.add(receiver);
- }
+ deadReceivers.add(receiver);
}
}
- // Broadcast status message
- HashMap<String,Long> statusMap = mLastStatusBroadcast.get(receiver);
- if (statusMap == null) {
- statusMap = new HashMap<String,Long>();
- mLastStatusBroadcast.put(receiver, statusMap);
- }
- long prevStatusUpdateTime =
- (statusMap.get(provider) != null) ? statusMap.get(provider) : 0;
-
+ long prevStatusUpdateTime = r.mLastStatusBroadcast;
if ((newStatusUpdateTime > prevStatusUpdateTime) &&
(prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
- statusMap.put(provider, newStatusUpdateTime);
+ r.mLastStatusBroadcast = newStatusUpdateTime;
if (!receiver.callStatusChangedLocked(provider, status, extras)) {
Log.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
if (deadReceivers == null) {
@@ -1719,70 +1614,28 @@
@Override
public void handleMessage(Message msg) {
try {
- if (msg.what == MESSAGE_HEARTBEAT) {
- // log("LocationWorkerHandler: Heartbeat!");
+ if (msg.what == MESSAGE_LOCATION_CHANGED) {
+ // log("LocationWorkerHandler: MESSAGE_LOCATION_CHANGED!");
- synchronized (mLocationListeners) {
- String provider = (String) msg.obj;
+ synchronized (mLock) {
+ Location location = (Location) msg.obj;
+
+ if (mCollector != null &&
+ LocationManager.GPS_PROVIDER.equals(location.getProvider())) {
+ try {
+ mCollector.updateLocation(location);
+ } catch (RemoteException e) {
+ Log.w(TAG, "mCollector.updateLocation failed");
+ mCollector = null;
+ }
+ }
+
+ String provider = location.getProvider();
if (!isAllowedBySettingsLocked(provider)) {
return;
}
- // Process the location fix if the screen is on or we're holding a wakelock
- if (mScreenOn || (mWakeLockAcquireTime != 0)) {
- handleLocationChangedLocked(provider);
- }
-
- // If it continues to have listeners
- ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
- if (records != null && records.size() > 0) {
- Message m = Message.obtain(this, MESSAGE_HEARTBEAT, provider);
- sendMessageAtTime(m, SystemClock.uptimeMillis() + 1000);
- }
-
- if ((mWakeLockAcquireTime != 0) &&
- (SystemClock.elapsedRealtime() - mWakeLockAcquireTime
- > MAX_TIME_FOR_WAKE_LOCK)) {
-
- removeMessages(MESSAGE_ACQUIRE_WAKE_LOCK);
- removeMessages(MESSAGE_RELEASE_WAKE_LOCK);
-
- log("LocationWorkerHandler: Exceeded max time for wake lock");
- Message m = Message.obtain(this, MESSAGE_RELEASE_WAKE_LOCK);
- sendMessageAtFrontOfQueue(m);
-
- } else if (mWakeLockAcquireTime != 0 &&
- mWakeLockGpsReceived && mWakeLockNetworkReceived) {
-
- removeMessages(MESSAGE_ACQUIRE_WAKE_LOCK);
- removeMessages(MESSAGE_RELEASE_WAKE_LOCK);
-
- log("LocationWorkerHandler: Locations received.");
- mWakeLockAcquireTime = 0;
- Message m = Message.obtain(this, MESSAGE_RELEASE_WAKE_LOCK);
- sendMessageDelayed(m, TIME_AFTER_WAKE_LOCK);
- }
- }
-
- } else if (msg.what == MESSAGE_ACQUIRE_WAKE_LOCK) {
- log("LocationWorkerHandler: Acquire");
- synchronized (mLocationListeners) {
- acquireWakeLockLocked();
- }
- } else if (msg.what == MESSAGE_RELEASE_WAKE_LOCK) {
- log("LocationWorkerHandler: Release");
-
- // Update wakelock status so the next alarm is set before releasing wakelock
- synchronized (mLocationListeners) {
- updateWakelockStatusLocked(mScreenOn);
- releaseWakeLockLocked();
- }
- } else if (msg.what == MESSAGE_INSTALL_NETWORK_LOCATION_PROVIDER) {
- synchronized (mLocationListeners) {
- Log.d(TAG, "installing network location provider");
- INetworkLocationManager.InstallCallback callback =
- (INetworkLocationManager.InstallCallback)msg.obj;
- callback.installNetworkLocationProvider(LocationManagerService.this);
+ handleLocationChangedLocked(location);
}
}
} catch (Exception e) {
@@ -1792,159 +1645,14 @@
}
}
- class CellLocationUpdater extends Thread {
- CellLocation mNextLocation;
-
- CellLocationUpdater() {
- super("CellLocationUpdater");
- }
-
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
- public void run() {
- int curAsu = -1;
- CellLocation curLocation = null;
-
- while (true) {
- // See if there is more work to do...
- synchronized (mLocationListeners) {
- if (curLocation == mNextLocation) {
- mCellLocationUpdater = null;
- break;
- }
-
- curLocation = mNextLocation;
- if (curLocation == null) {
- mCellLocationUpdater = null;
- break;
- }
-
- curAsu = mLastSignalStrength;
-
- mNextLocation = null;
- }
-
- try {
- // Gets cell state. This can block so must be done without
- // locks held.
- CellState cs = new CellState(mTelephonyManager, curLocation, curAsu);
-
- synchronized (mLocationListeners) {
- mLastCellState = cs;
-
- cs.updateSignalStrength(mLastSignalStrength);
- cs.updateRadioType(mLastRadioType);
-
- // Notify collector
- if (mCollector != null) {
- mCollector.updateCellState(cs);
- }
-
- // Updates providers
- List<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
- for (LocationProviderImpl provider : providers) {
- if (provider.requiresCell()) {
- provider.updateCellState(cs);
- }
- }
- }
- } catch (RuntimeException e) {
- Log.e(TAG, "Exception in PhoneStateListener.onCellLocationChanged:", e);
- }
- }
- }
- }
-
- CellLocationUpdater mCellLocationUpdater = null;
- CellState mLastCellState = null;
- int mLastSignalStrength = -1;
- int mLastRadioType = -1;
-
- PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
-
- @Override
- public void onCellLocationChanged(CellLocation cellLocation) {
- synchronized (mLocationListeners) {
- if (mCellLocationUpdater == null) {
- mCellLocationUpdater = new CellLocationUpdater();
- mCellLocationUpdater.start();
- }
- mCellLocationUpdater.mNextLocation = cellLocation;
- }
- }
-
- @Override
- public void onSignalStrengthChanged(int asu) {
- synchronized (mLocationListeners) {
- mLastSignalStrength = asu;
-
- if (mLastCellState != null) {
- mLastCellState.updateSignalStrength(asu);
- }
- }
- }
-
- @Override
- public void onDataConnectionStateChanged(int state) {
- synchronized (mLocationListeners) {
- // Get radio type
- int radioType = mTelephonyManager.getNetworkType();
- if (radioType == TelephonyManager.NETWORK_TYPE_GPRS ||
- radioType == TelephonyManager.NETWORK_TYPE_EDGE) {
- radioType = CellState.RADIO_TYPE_GPRS;
- } else if (radioType == TelephonyManager.NETWORK_TYPE_UMTS) {
- radioType = CellState.RADIO_TYPE_WCDMA;
- }
- mLastRadioType = radioType;
-
- if (mLastCellState != null) {
- mLastCellState.updateRadioType(radioType);
- }
- }
- }
- };
-
- private class PowerStateBroadcastReceiver extends BroadcastReceiver {
- @Override public void onReceive(Context context, Intent intent) {
+ public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
- if (action.equals(ALARM_INTENT)) {
- synchronized (mLocationListeners) {
- log("PowerStateBroadcastReceiver: Alarm received");
- mLocationHandler.removeMessages(MESSAGE_ACQUIRE_WAKE_LOCK);
- // Have to do this immediately, rather than posting a
- // message, so we execute our code while the system
- // is holding a wake lock until the alarm broadcast
- // is finished.
- acquireWakeLockLocked();
- }
-
- } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
- log("PowerStateBroadcastReceiver: Screen off");
- synchronized (mLocationListeners) {
- updateWakelockStatusLocked(false);
- }
-
- } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
- log("PowerStateBroadcastReceiver: Screen on");
- synchronized (mLocationListeners) {
- updateWakelockStatusLocked(true);
- }
-
- } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
- log("PowerStateBroadcastReceiver: Battery changed");
- synchronized (mLocationListeners) {
- int scale = intent.getIntExtra(BATTERY_EXTRA_SCALE, 100);
- int level = intent.getIntExtra(BATTERY_EXTRA_LEVEL, 0);
- boolean plugged = intent.getIntExtra(BATTERY_EXTRA_PLUGGED, 0) != 0;
-
- // Notify collector battery state
- if (mCollector != null) {
- mCollector.updateBatteryState(scale, level, plugged);
- }
- }
- } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
+ if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
|| action.equals(Intent.ACTION_PACKAGE_RESTARTED)) {
- synchronized (mLocationListeners) {
+ synchronized (mLock) {
int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
if (uid >= 0) {
ArrayList<Receiver> removedRecs = null;
@@ -1984,32 +1692,6 @@
}
}
}
- }
- }
- }
-
- private class NetworkStateBroadcastReceiver extends BroadcastReceiver {
- @Override public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
-
- if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
-
- List<ScanResult> wifiScanResults = mWifiManager.getScanResults();
-
- if (wifiScanResults == null) {
- return;
- }
-
- // Notify provider and collector of Wifi scan results
- synchronized (mLocationListeners) {
- if (mCollector != null) {
- mCollector.updateWifiScanResults(wifiScanResults);
- }
- if (mNetworkLocationInterface != null) {
- mNetworkLocationInterface.updateWifiScanResults(wifiScanResults);
- }
- }
-
} else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
boolean noConnectivity =
intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
@@ -2020,484 +1702,92 @@
}
// Notify location providers of current network state
- synchronized (mLocationListeners) {
- List<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
- for (LocationProviderImpl provider : providers) {
+ synchronized (mLock) {
+ for (int i = mProviders.size() - 1; i >= 0; i--) {
+ LocationProviderProxy provider = mProviders.get(i);
if (provider.requiresNetwork()) {
provider.updateNetworkState(mNetworkState);
}
}
}
-
- } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
- int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
- WifiManager.WIFI_STATE_UNKNOWN);
-
- if (state == WifiManager.WIFI_STATE_ENABLED) {
- mWifiEnabled = true;
- } else if (state == WifiManager.WIFI_STATE_DISABLED) {
- mWifiEnabled = false;
- } else {
- return;
- }
-
- // Notify network provider of current wifi enabled state
- synchronized (mLocationListeners) {
- if (mNetworkLocationInterface != null) {
- mNetworkLocationInterface.updateWifiEnabledState(mWifiEnabled);
- }
- }
-
- } else if (action.equals(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION)) {
-
- final boolean enabled = intent.getBooleanExtra(GpsLocationProvider.EXTRA_ENABLED,
- false);
-
- synchronized (mLocationListeners) {
- if (enabled) {
- updateReportedGpsLocked();
- mGpsNavigating = true;
- } else {
- reportStopGpsLocked();
- mGpsNavigating = false;
- // When GPS is disabled, we are OK to release wake-lock
- mWakeLockGpsReceived = true;
- }
- }
}
-
}
- }
+ };
// Wake locks
- private void updateWakelockStatusLocked(boolean screenOn) {
- log("updateWakelockStatus(): " + screenOn);
-
- long callerId = Binder.clearCallingIdentity();
-
- boolean needsLock = false;
- long minTime = Integer.MAX_VALUE;
-
- if (mNetworkLocationProvider != null && mNetworkLocationProvider.isLocationTracking()) {
- needsLock = true;
- minTime = Math.min(mNetworkLocationProvider.getMinTime(), minTime);
- }
-
- if (mGpsLocationProvider != null && mGpsLocationProvider.isLocationTracking()) {
- needsLock = true;
- minTime = Math.min(mGpsLocationProvider.getMinTime(), minTime);
- if (screenOn) {
- startGpsLocked();
- } else if (mScreenOn && !screenOn) {
- // We just turned the screen off so stop navigating
- stopGpsLocked();
- }
- }
-
- mScreenOn = screenOn;
-
- PendingIntent sender =
- PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_INTENT), 0);
-
- // Cancel existing alarm
- log("Cancelling existing alarm");
- mAlarmManager.cancel(sender);
-
- if (needsLock && !mScreenOn) {
- long now = SystemClock.elapsedRealtime();
- mAlarmManager.set(
- AlarmManager.ELAPSED_REALTIME_WAKEUP, now + minTime, sender);
- mAlarmInterval = minTime;
- log("Creating a new wakelock alarm with minTime = " + minTime);
- } else {
- log("No need for alarm");
- mAlarmInterval = -1;
-
- // Clear out existing wakelocks
- mLocationHandler.removeMessages(MESSAGE_ACQUIRE_WAKE_LOCK);
- mLocationHandler.removeMessages(MESSAGE_RELEASE_WAKE_LOCK);
- releaseWakeLockLocked();
- }
- Binder.restoreCallingIdentity(callerId);
- }
-
- private void acquireWakeLockLocked() {
- try {
- acquireWakeLockXLocked();
- } catch (Exception e) {
- // This is to catch a runtime exception thrown when we try to release an
- // already released lock.
- Log.e(TAG, "exception in acquireWakeLock()", e);
- }
- }
-
- private void acquireWakeLockXLocked() {
- if (mWakeLock.isHeld()) {
- log("Must release wakelock before acquiring");
- mWakeLockAcquireTime = 0;
- mWakeLock.release();
- }
-
- boolean networkActive = (mNetworkLocationProvider != null)
- && mNetworkLocationProvider.isLocationTracking();
- boolean gpsActive = (mGpsLocationProvider != null)
- && mGpsLocationProvider.isLocationTracking();
-
- boolean needsLock = networkActive || gpsActive;
- if (!needsLock) {
- log("No need for Lock!");
- return;
- }
-
- mWakeLockGpsReceived = !gpsActive;
- mWakeLockNetworkReceived = !networkActive;
-
- // Acquire wake lock
- mWakeLock.acquire();
- mWakeLockAcquireTime = SystemClock.elapsedRealtime();
- log("Acquired wakelock");
-
- // Start the gps provider
- startGpsLocked();
-
- // Acquire cell lock
- if (mCellWakeLockAcquired) {
- // Lock is already acquired
- } else if (!mWakeLockNetworkReceived) {
- mTelephonyManager.enableLocationUpdates();
- mCellWakeLockAcquired = true;
- } else {
- mCellWakeLockAcquired = false;
- }
-
- // Notify NetworkLocationProvider
- if (mNetworkLocationInterface != null) {
- mNetworkLocationInterface.updateCellLockStatus(mCellWakeLockAcquired);
- }
-
- // Acquire wifi lock
- WifiManager.WifiLock wifiLock = getWifiWakelockLocked();
- if (wifiLock != null) {
- if (mWifiWakeLockAcquired) {
- // Lock is already acquired
- } else if (mWifiManager.isWifiEnabled() && !mWakeLockNetworkReceived) {
- wifiLock.acquire();
- mWifiWakeLockAcquired = true;
- } else {
- mWifiWakeLockAcquired = false;
- Log.w(TAG, "acquireWakeLock(): Unable to get WiFi lock");
- }
- }
- }
-
- private boolean reportGpsUidLocked(int curSeq, int nextSeq, int uid) {
- int seq = mReportedGpsUids.get(uid, -1);
- if (seq == curSeq) {
- // Already reported; propagate to next sequence.
- mReportedGpsUids.put(uid, nextSeq);
- return true;
- } else if (seq != nextSeq) {
- try {
- // New UID; report it.
- mBatteryStats.noteStartGps(uid);
- mReportedGpsUids.put(uid, nextSeq);
- return true;
- } catch (RemoteException e) {
- }
- }
- return false;
- }
-
- private void updateReportedGpsLocked() {
- if (mGpsLocationProvider == null) {
- return;
- }
-
- final String name = mGpsLocationProvider.getName();
- final int curSeq = mReportedGpsSeq;
- final int nextSeq = (curSeq+1) >= 0 ? (curSeq+1) : 0;
- mReportedGpsSeq = nextSeq;
-
- ArrayList<UpdateRecord> urs = mRecordsByProvider.get(name);
- int num = 0;
- final int N = urs.size();
- for (int i=0; i<N; i++) {
- UpdateRecord ur = urs.get(i);
- if (ur.mReceiver == mProximityListener) {
- // We don't want the system to take the blame for this one.
- continue;
- }
- if (reportGpsUidLocked(curSeq, nextSeq, ur.mUid)) {
- num++;
- }
- }
-
- for (ProximityAlert pe : mProximityAlerts.values()) {
- if (reportGpsUidLocked(curSeq, nextSeq, pe.mUid)) {
- num++;
- }
- }
-
- if (num != mReportedGpsUids.size()) {
- // The number of uids is processed is different than the
- // array; report any that are no longer active.
- for (int i=mReportedGpsUids.size()-1; i>=0; i--) {
- if (mReportedGpsUids.valueAt(i) != nextSeq) {
- try {
- mBatteryStats.noteStopGps(mReportedGpsUids.keyAt(i));
- } catch (RemoteException e) {
- }
- mReportedGpsUids.removeAt(i);
- }
- }
- }
- }
-
- private void reportStopGpsLocked() {
- int curSeq = mReportedGpsSeq;
- for (int i=mReportedGpsUids.size()-1; i>=0; i--) {
- if (mReportedGpsUids.valueAt(i) == curSeq) {
+ private void incrementPendingBroadcasts() {
+ synchronized (mWakeLock) {
+ if (mPendingBroadcasts++ == 0) {
try {
- mBatteryStats.noteStopGps(mReportedGpsUids.keyAt(i));
- } catch (RemoteException e) {
+ mWakeLock.acquire();
+ log("Acquired wakelock");
+ } catch (Exception e) {
+ // This is to catch a runtime exception thrown when we try to release an
+ // already released lock.
+ Log.e(TAG, "exception in acquireWakeLock()", e);
}
}
}
- curSeq++;
- if (curSeq < 0) curSeq = 0;
- mReportedGpsSeq = curSeq;
- mReportedGpsUids.clear();
- }
-
- private void startGpsLocked() {
- boolean gpsActive = (mGpsLocationProvider != null)
- && mGpsLocationProvider.isLocationTracking();
- if (gpsActive) {
- mGpsLocationProvider.startNavigating();
- }
}
- private void stopGpsLocked() {
- boolean gpsActive = mGpsLocationProvider != null
- && mGpsLocationProvider.isLocationTracking();
- if (gpsActive) {
- mGpsLocationProvider.stopNavigating();
- }
- }
-
- private void releaseWakeLockLocked() {
- try {
- releaseWakeLockXLocked();
- } catch (Exception e) {
- // This is to catch a runtime exception thrown when we try to release an
- // already released lock.
- Log.e(TAG, "exception in releaseWakeLock()", e);
- }
- }
-
- private void releaseWakeLockXLocked() {
- // Release wifi lock
- WifiManager.WifiLock wifiLock = getWifiWakelockLocked();
- if (wifiLock != null) {
- if (mWifiWakeLockAcquired) {
- wifiLock.release();
- mWifiWakeLockAcquired = false;
+ private void decrementPendingBroadcasts() {
+ synchronized (mWakeLock) {
+ if (--mPendingBroadcasts == 0) {
+ try {
+ // Release wake lock
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ log("Released wakelock");
+ } else {
+ log("Can't release wakelock again!");
+ }
+ } catch (Exception e) {
+ // This is to catch a runtime exception thrown when we try to release an
+ // already released lock.
+ Log.e(TAG, "exception in releaseWakeLock()", e);
+ }
}
}
-
- if (!mScreenOn) {
- // Stop the gps
- stopGpsLocked();
- }
-
- // Release cell lock
- if (mCellWakeLockAcquired) {
- mTelephonyManager.disableLocationUpdates();
- mCellWakeLockAcquired = false;
- }
-
- // Notify NetworkLocationProvider
- if (mNetworkLocationInterface != null) {
- mNetworkLocationInterface.updateCellLockStatus(mCellWakeLockAcquired);
- }
-
- // Release wake lock
- mWakeLockAcquireTime = 0;
- if (mWakeLock.isHeld()) {
- log("Released wakelock");
- mWakeLock.release();
- } else {
- log("Can't release wakelock again!");
- }
}
// Geocoder
public String getFromLocation(double latitude, double longitude, int maxResults,
- String language, String country, String variant, String appName, List<Address> addrs) {
- synchronized (mLocationListeners) {
- if (mNetworkLocationInterface != null) {
- return mNetworkLocationInterface.getFromLocation(latitude, longitude, maxResults,
- language, country, variant, appName, addrs);
- } else {
- return null;
+ String language, String country, String variant, String appName, List<Address> addrs) {
+ if (mGeocodeProvider != null) {
+ try {
+ return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults, language, country,
+ variant, appName, addrs);
+ } catch (RemoteException e) {
+ Log.e(TAG, "getFromLocation failed", e);
+ mGeocodeProvider = null;
}
}
+ return null;
}
+
public String getFromLocationName(String locationName,
- double lowerLeftLatitude, double lowerLeftLongitude,
- double upperRightLatitude, double upperRightLongitude, int maxResults,
- String language, String country, String variant, String appName, List<Address> addrs) {
- synchronized (mLocationListeners) {
- if (mNetworkLocationInterface != null) {
- return mNetworkLocationInterface.getFromLocationName(locationName, lowerLeftLatitude,
- lowerLeftLongitude, upperRightLatitude, upperRightLongitude, maxResults,
- language, country, variant, appName, addrs);
- } else {
- return null;
+ double lowerLeftLatitude, double lowerLeftLongitude,
+ double upperRightLatitude, double upperRightLongitude, int maxResults,
+ String language, String country, String variant, String appName, List<Address> addrs) {
+
+ if (mGeocodeProvider != null) {
+ try {
+ return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
+ lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
+ maxResults, language, country, variant, appName, addrs);
+ } catch (RemoteException e) {
+ Log.e(TAG, "getFromLocationName failed", e);
+ mGeocodeProvider = null;
}
}
+ return null;
}
// Mock Providers
- class MockProvider extends LocationProviderImpl {
- boolean mRequiresNetwork;
- boolean mRequiresSatellite;
- boolean mRequiresCell;
- boolean mHasMonetaryCost;
- boolean mSupportsAltitude;
- boolean mSupportsSpeed;
- boolean mSupportsBearing;
- int mPowerRequirement;
- int mAccuracy;
-
- public MockProvider(String name, boolean requiresNetwork, boolean requiresSatellite,
- boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
- boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
- super(name);
-
- mRequiresNetwork = requiresNetwork;
- mRequiresSatellite = requiresSatellite;
- mRequiresCell = requiresCell;
- mHasMonetaryCost = hasMonetaryCost;
- mSupportsAltitude = supportsAltitude;
- mSupportsBearing = supportsBearing;
- mSupportsSpeed = supportsSpeed;
- mPowerRequirement = powerRequirement;
- mAccuracy = accuracy;
- }
-
- @Override
- public void disable() {
- String name = getName();
- // We shouldn't normally need to lock, since this should only be called
- // by the service with the lock held, but let's be paranid.
- synchronized (mLocationListeners) {
- mEnabledProviders.remove(name);
- mDisabledProviders.add(name);
- }
- }
-
- @Override
- public void enable() {
- String name = getName();
- // We shouldn't normally need to lock, since this should only be called
- // by the service with the lock held, but let's be paranid.
- synchronized (mLocationListeners) {
- mEnabledProviders.add(name);
- mDisabledProviders.remove(name);
- }
- }
-
- @Override
- public boolean getLocation(Location l) {
- // We shouldn't normally need to lock, since this should only be called
- // by the service with the lock held, but let's be paranid.
- synchronized (mLocationListeners) {
- Location loc = mMockProviderLocation.get(getName());
- if (loc == null) {
- return false;
- }
- l.set(loc);
- return true;
- }
- }
-
- @Override
- public int getStatus(Bundle extras) {
- // We shouldn't normally need to lock, since this should only be called
- // by the service with the lock held, but let's be paranid.
- synchronized (mLocationListeners) {
- String name = getName();
- Integer s = mMockProviderStatus.get(name);
- int status = (s == null) ? AVAILABLE : s.intValue();
- Bundle newExtras = mMockProviderStatusExtras.get(name);
- if (newExtras != null) {
- extras.clear();
- extras.putAll(newExtras);
- }
- return status;
- }
- }
-
- @Override
- public boolean isEnabled() {
- // We shouldn't normally need to lock, since this should only be called
- // by the service with the lock held, but let's be paranid.
- synchronized (mLocationListeners) {
- return mEnabledProviders.contains(getName());
- }
- }
-
- @Override
- public int getAccuracy() {
- return mAccuracy;
- }
-
- @Override
- public int getPowerRequirement() {
- return mPowerRequirement;
- }
-
- @Override
- public boolean hasMonetaryCost() {
- return mHasMonetaryCost;
- }
-
- @Override
- public boolean requiresCell() {
- return mRequiresCell;
- }
-
- @Override
- public boolean requiresNetwork() {
- return mRequiresNetwork;
- }
-
- @Override
- public boolean requiresSatellite() {
- return mRequiresSatellite;
- }
-
- @Override
- public boolean supportsAltitude() {
- return mSupportsAltitude;
- }
-
- @Override
- public boolean supportsBearing() {
- return mSupportsBearing;
- }
-
- @Override
- public boolean supportsSpeed() {
- return mSupportsSpeed;
- }
- }
-
private void checkMockPermissionsSafe() {
boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1;
@@ -2516,60 +1806,75 @@
boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
checkMockPermissionsSafe();
- synchronized (mLocationListeners) {
- MockProvider provider = new MockProvider(name, requiresNetwork, requiresSatellite,
+ synchronized (mLock) {
+ MockProvider provider = new MockProvider(name, this,
+ requiresNetwork, requiresSatellite,
requiresCell, hasMonetaryCost, supportsAltitude,
supportsSpeed, supportsBearing, powerRequirement, accuracy);
- if (LocationProviderImpl.getProvider(name) != null) {
+ if (mProvidersByName.get(name) != null) {
throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
}
- LocationProviderImpl.addProvider(provider);
+
+ // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
+ long identity = Binder.clearCallingIdentity();
+ addProvider(new LocationProviderProxy(name, provider));
+ mMockProviders.put(name, provider);
updateProvidersLocked();
+ Binder.restoreCallingIdentity(identity);
}
}
public void removeTestProvider(String provider) {
checkMockPermissionsSafe();
- synchronized (mLocationListeners) {
- LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
- if (p == null) {
+ synchronized (mLock) {
+ MockProvider mockProvider = mMockProviders.get(provider);
+ if (mockProvider == null) {
throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
}
- LocationProviderImpl.removeProvider(p);
+ removeProvider(mProvidersByName.get(provider));
+ mMockProviders.remove(mockProvider);
updateProvidersLocked();
}
}
public void setTestProviderLocation(String provider, Location loc) {
checkMockPermissionsSafe();
- synchronized (mLocationListeners) {
- if (LocationProviderImpl.getProvider(provider) == null) {
+ synchronized (mLock) {
+ MockProvider mockProvider = mMockProviders.get(provider);
+ if (mockProvider == null) {
throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
}
- mMockProviderLocation.put(provider, loc);
+ // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
+ long identity = Binder.clearCallingIdentity();
+ mockProvider.setLocation(loc);
+ Binder.restoreCallingIdentity(identity);
}
}
public void clearTestProviderLocation(String provider) {
checkMockPermissionsSafe();
- synchronized (mLocationListeners) {
- if (LocationProviderImpl.getProvider(provider) == null) {
+ synchronized (mLock) {
+ MockProvider mockProvider = mMockProviders.get(provider);
+ if (mockProvider == null) {
throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
}
- mMockProviderLocation.remove(provider);
+ mockProvider.clearLocation();
}
}
public void setTestProviderEnabled(String provider, boolean enabled) {
checkMockPermissionsSafe();
- synchronized (mLocationListeners) {
- if (LocationProviderImpl.getProvider(provider) == null) {
+ synchronized (mLock) {
+ MockProvider mockProvider = mMockProviders.get(provider);
+ if (mockProvider == null) {
throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
}
if (enabled) {
+ mockProvider.enable();
mEnabledProviders.add(provider);
mDisabledProviders.remove(provider);
} else {
+ mockProvider.disable();
mEnabledProviders.remove(provider);
mDisabledProviders.add(provider);
}
@@ -2579,8 +1884,9 @@
public void clearTestProviderEnabled(String provider) {
checkMockPermissionsSafe();
- synchronized (mLocationListeners) {
- if (LocationProviderImpl.getProvider(provider) == null) {
+ synchronized (mLock) {
+ MockProvider mockProvider = mMockProviders.get(provider);
+ if (mockProvider == null) {
throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
}
mEnabledProviders.remove(provider);
@@ -2591,25 +1897,23 @@
public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) {
checkMockPermissionsSafe();
- synchronized (mLocationListeners) {
- if (LocationProviderImpl.getProvider(provider) == null) {
+ synchronized (mLock) {
+ MockProvider mockProvider = mMockProviders.get(provider);
+ if (mockProvider == null) {
throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
}
- mMockProviderStatus.put(provider, new Integer(status));
- mMockProviderStatusExtras.put(provider, extras);
- mMockProviderStatusUpdateTime.put(provider, new Long(updateTime));
+ mockProvider.setStatus(status, extras, updateTime);
}
}
public void clearTestProviderStatus(String provider) {
checkMockPermissionsSafe();
- synchronized (mLocationListeners) {
- if (LocationProviderImpl.getProvider(provider) == null) {
+ synchronized (mLock) {
+ MockProvider mockProvider = mMockProviders.get(provider);
+ if (mockProvider == null) {
throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
}
- mMockProviderStatus.remove(provider);
- mMockProviderStatusExtras.remove(provider);
- mMockProviderStatusUpdateTime.remove(provider);
+ mockProvider.clearStatus();
}
}
@@ -2622,63 +1926,29 @@
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="
+ pw.println("Permission Denial: can't dump LocationManagerService from from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
return;
}
- synchronized (mLocationListeners) {
+ synchronized (mLock) {
pw.println("Current Location Manager state:");
pw.println(" sProvidersLoaded=" + sProvidersLoaded);
- pw.println(" mGpsLocationProvider=" + mGpsLocationProvider);
- pw.println(" mGpsNavigating=" + mGpsNavigating);
- pw.println(" mNetworkLocationProvider=" + mNetworkLocationProvider);
- pw.println(" mNetworkLocationInterface=" + mNetworkLocationInterface);
- pw.println(" mLastSignalStrength=" + mLastSignalStrength
- + " mLastRadioType=" + mLastRadioType);
- pw.println(" mCellLocationUpdater=" + mCellLocationUpdater);
- pw.println(" mLastCellState=" + mLastCellState);
pw.println(" mCollector=" + mCollector);
- pw.println(" mAlarmInterval=" + mAlarmInterval
- + " mScreenOn=" + mScreenOn
- + " mWakeLockAcquireTime=" + mWakeLockAcquireTime);
- pw.println(" mWakeLockGpsReceived=" + mWakeLockGpsReceived
- + " mWakeLockNetworkReceived=" + mWakeLockNetworkReceived);
- pw.println(" mWifiWakeLockAcquired=" + mWifiWakeLockAcquired
- + " mCellWakeLockAcquired=" + mCellWakeLockAcquired);
pw.println(" Listeners:");
- int N = mListeners.size();
+ int N = mReceivers.size();
for (int i=0; i<N; i++) {
- pw.println(" " + mListeners.get(i));
+ pw.println(" " + mReceivers.get(i));
}
pw.println(" Location Listeners:");
- for (Map.Entry<Receiver, HashMap<String,UpdateRecord>> i
- : mLocationListeners.entrySet()) {
- pw.println(" " + i.getKey() + ":");
- for (Map.Entry<String,UpdateRecord> j : i.getValue().entrySet()) {
+ for (Receiver i : mReceivers.values()) {
+ pw.println(" " + i + ":");
+ for (Map.Entry<String,UpdateRecord> j : i.mUpdateRecords.entrySet()) {
pw.println(" " + j.getKey() + ":");
j.getValue().dump(pw, " ");
}
}
- pw.println(" Last Fix Broadcasts:");
- for (Map.Entry<Receiver, HashMap<String,Location>> i
- : mLastFixBroadcast.entrySet()) {
- pw.println(" " + i.getKey() + ":");
- for (Map.Entry<String,Location> j : i.getValue().entrySet()) {
- pw.println(" " + j.getKey() + ":");
- j.getValue().dump(new PrintWriterPrinter(pw), " ");
- }
- }
- pw.println(" Last Status Broadcasts:");
- for (Map.Entry<Receiver, HashMap<String,Long>> i
- : mLastStatusBroadcast.entrySet()) {
- pw.println(" " + i.getKey() + ":");
- for (Map.Entry<String,Long> j : i.getValue().entrySet()) {
- pw.println(" " + j.getKey() + " -> 0x"
- + Long.toHexString(j.getValue()));
- }
- }
pw.println(" Records by Provider:");
for (Map.Entry<String, ArrayList<UpdateRecord>> i
: mRecordsByProvider.entrySet()) {
@@ -2688,12 +1958,6 @@
j.dump(pw, " ");
}
}
- pw.println(" Locations by Provider:");
- for (Map.Entry<String, Location> i
- : mLocationsByProvider.entrySet()) {
- pw.println(" " + i.getKey() + ":");
- i.getValue().dump(new PrintWriterPrinter(pw), " ");
- }
pw.println(" Last Known Locations:");
for (Map.Entry<String, Location> i
: mLastKnownLocation.entrySet()) {
@@ -2715,6 +1979,7 @@
i.dump(pw, " ");
}
}
+ pw.println(" mProximityReceiver=" + mProximityReceiver);
pw.println(" mProximityListener=" + mProximityListener);
if (mEnabledProviders.size() > 0) {
pw.println(" Enabled Providers:");
@@ -2733,42 +1998,9 @@
if (mMockProviders.size() > 0) {
pw.println(" Mock Providers:");
for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
- pw.println(" " + i.getKey() + " -> " + i.getValue());
+ i.getValue().dump(pw, " ");
}
}
- if (mMockProviderLocation.size() > 0) {
- pw.println(" Mock Provider Location:");
- for (Map.Entry<String, Location> i : mMockProviderLocation.entrySet()) {
- pw.println(" " + i.getKey() + ":");
- i.getValue().dump(new PrintWriterPrinter(pw), " ");
- }
- }
- if (mMockProviderStatus.size() > 0) {
- pw.println(" Mock Provider Status:");
- for (Map.Entry<String, Integer> i : mMockProviderStatus.entrySet()) {
- pw.println(" " + i.getKey() + " -> 0x"
- + Integer.toHexString(i.getValue()));
- }
- }
- if (mMockProviderStatusExtras.size() > 0) {
- pw.println(" Mock Provider Status Extras:");
- for (Map.Entry<String, Bundle> i : mMockProviderStatusExtras.entrySet()) {
- pw.println(" " + i.getKey() + " -> " + i.getValue());
- }
- }
- if (mMockProviderStatusUpdateTime.size() > 0) {
- pw.println(" Mock Provider Status Update Time:");
- for (Map.Entry<String, Long> i : mMockProviderStatusUpdateTime.entrySet()) {
- pw.println(" " + i.getKey() + " -> " + i.getValue());
- }
- }
- pw.println(" Reported GPS UIDs @ seq " + mReportedGpsSeq + ":");
- N = mReportedGpsUids.size();
- for (int i=0; i<N; i++) {
- pw.println(" UID " + mReportedGpsUids.keyAt(i)
- + " seq=" + mReportedGpsUids.valueAt(i));
- }
}
}
}
-
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 9e062f4..4ee0c91 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -59,6 +59,7 @@
import android.content.pm.Signature;
import android.net.Uri;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.HandlerThread;
import android.os.Parcel;
@@ -140,8 +141,9 @@
Process.THREAD_PRIORITY_BACKGROUND);
final Handler mHandler;
- final int mSdkVersion = SystemProperties.getInt(
- "ro.build.version.sdk", 0);
+ final int mSdkVersion = Build.VERSION.SDK_INT;
+ final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
+ ? null : Build.VERSION.CODENAME;
final Context mContext;
final boolean mFactoryTest;
@@ -1751,7 +1753,7 @@
parseFlags |= mDefParseFlags;
PackageParser pp = new PackageParser(scanFile.getPath());
pp.setSeparateProcesses(mSeparateProcesses);
- pp.setSdkVersion(mSdkVersion);
+ pp.setSdkVersion(mSdkVersion, mSdkCodename);
final PackageParser.Package pkg = pp.parsePackage(scanFile,
destCodeFile.getAbsolutePath(), mMetrics, parseFlags);
if (pkg == null) {
@@ -1761,8 +1763,7 @@
PackageSetting ps;
PackageSetting updatedPkg;
synchronized (mPackages) {
- ps = mSettings.peekPackageLP(pkg.packageName,
- scanFile.toString());
+ ps = mSettings.peekPackageLP(pkg.packageName);
updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
}
if (updatedPkg != null) {
@@ -1771,13 +1772,21 @@
}
if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
// Check for updated system applications here
- if ((updatedPkg != null) && (ps == null)) {
- // The system package has been updated and the code path does not match
- // Ignore entry. Just return
- Log.w(TAG, "Package:" + pkg.packageName +
- " has been updated. Ignoring the one from path:"+scanFile);
- mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
- return null;
+ if (updatedPkg != null) {
+ if ((ps != null) && (!ps.codePath.getPath().equals(scanFile.getPath()))) {
+ if (pkg.mVersionCode <= ps.versionCode) {
+ // The system package has been updated and the code path does not match
+ // Ignore entry. Just return
+ Log.w(TAG, "Package:" + pkg.packageName +
+ " has been updated. Ignoring the one from path:"+scanFile);
+ mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
+ return null;
+ } else {
+ // Delete the older apk pointed to by ps
+ deletePackageResourcesLI(ps.name, ps.codePathString, ps.resourcePathString);
+ mSettings.enableSystemPackageLP(ps.name);
+ }
+ }
}
}
if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
@@ -2932,11 +2941,12 @@
}
@Override
- protected void dumpFilter(Printer out, String prefix,
+ protected void dumpFilter(PrintWriter out, String prefix,
PackageParser.ActivityIntentInfo filter) {
- out.println(prefix
- + Integer.toHexString(System.identityHashCode(filter.activity))
- + " " + filter.activity.component.flattenToShortString());
+ out.print(prefix); out.print(
+ Integer.toHexString(System.identityHashCode(filter.activity)));
+ out.print(' ');
+ out.println(filter.activity.componentShortName);
}
// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
@@ -3064,11 +3074,12 @@
}
@Override
- protected void dumpFilter(Printer out, String prefix,
+ protected void dumpFilter(PrintWriter out, String prefix,
PackageParser.ServiceIntentInfo filter) {
- out.println(prefix
- + Integer.toHexString(System.identityHashCode(filter.service))
- + " " + filter.service.component.flattenToShortString());
+ out.print(prefix); out.print(
+ Integer.toHexString(System.identityHashCode(filter.service)));
+ out.print(' ');
+ out.println(filter.service.componentShortName);
}
// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
@@ -3220,20 +3231,27 @@
private final String mRootDir;
private final boolean mIsRom;
}
-
+
/* Called when a downloaded package installation has been confirmed by the user */
public void installPackage(
final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
+ installPackage(packageURI, observer, flags, null);
+ }
+
+ /* Called when a downloaded package installation has been confirmed by the user */
+ public void installPackage(
+ final Uri packageURI, final IPackageInstallObserver observer, final int flags,
+ final String installerPackageName) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.INSTALL_PACKAGES, null);
-
+
// Queue up an async operation since the package installation may take a little while.
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
PackageInstalledInfo res;
synchronized (mInstallLock) {
- res = installPackageLI(packageURI, flags, true);
+ res = installPackageLI(packageURI, flags, true, installerPackageName);
}
if (observer != null) {
try {
@@ -3281,7 +3299,7 @@
File tmpPackageFile,
String destFilePath, File destPackageFile, File destResourceFile,
PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
- PackageInstalledInfo res) {
+ String installerPackageName, PackageInstalledInfo res) {
// Remember this for later, in case we need to rollback this install
boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists();
res.name = pkgName;
@@ -3317,7 +3335,8 @@
destResourceFile, pkg,
newPackage,
true,
- forwardLocked,
+ forwardLocked,
+ installerPackageName,
res);
// delete the partially installed application. the data directory will have to be
// restored if it was already existing
@@ -3338,26 +3357,27 @@
File tmpPackageFile,
String destFilePath, File destPackageFile, File destResourceFile,
PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
- PackageInstalledInfo res) {
- PackageParser.Package deletedPackage;
+ String installerPackageName, PackageInstalledInfo res) {
+
+ PackageParser.Package oldPackage;
// First find the old package info and check signatures
synchronized(mPackages) {
- deletedPackage = mPackages.get(pkgName);
- if(checkSignaturesLP(pkg, deletedPackage) != PackageManager.SIGNATURE_MATCH) {
+ oldPackage = mPackages.get(pkgName);
+ if(checkSignaturesLP(pkg, oldPackage) != PackageManager.SIGNATURE_MATCH) {
res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
return;
}
}
- boolean sysPkg = ((deletedPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
+ boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
if(sysPkg) {
- replaceSystemPackageLI(deletedPackage,
+ replaceSystemPackageLI(oldPackage,
tmpPackageFile, destFilePath,
destPackageFile, destResourceFile, pkg, forwardLocked,
- newInstall, res);
+ newInstall, installerPackageName, res);
} else {
- replaceNonSystemPackageLI(deletedPackage, tmpPackageFile, destFilePath,
+ replaceNonSystemPackageLI(oldPackage, tmpPackageFile, destFilePath,
destPackageFile, destResourceFile, pkg, forwardLocked,
- newInstall, res);
+ newInstall, installerPackageName, res);
}
}
@@ -3365,12 +3385,18 @@
File tmpPackageFile,
String destFilePath, File destPackageFile, File destResourceFile,
PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
- PackageInstalledInfo res) {
+ String installerPackageName, PackageInstalledInfo res) {
PackageParser.Package newPackage = null;
String pkgName = deletedPackage.packageName;
boolean deletedPkg = true;
boolean updatedSettings = false;
- int parseFlags = PackageManager.REPLACE_EXISTING_PACKAGE;
+
+ String oldInstallerPackageName = null;
+ synchronized (mPackages) {
+ oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
+ }
+
+ int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING;
// First delete the existing package while retaining the data directory
if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
res.removedInfo)) {
@@ -3398,6 +3424,7 @@
newPackage,
true,
forwardLocked,
+ installerPackageName,
res);
updatedSettings = true;
}
@@ -3441,8 +3468,8 @@
installPackageLI(
Uri.fromFile(new File(deletedPackage.mPath)),
isForwardLocked(deletedPackage)
- ? PackageManager.FORWARD_LOCK_PACKAGE
- : 0, false);
+ ? PackageManager.INSTALL_FORWARD_LOCK
+ : 0, false, oldInstallerPackageName);
}
}
}
@@ -3451,10 +3478,10 @@
File tmpPackageFile,
String destFilePath, File destPackageFile, File destResourceFile,
PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
- PackageInstalledInfo res) {
+ String installerPackageName, PackageInstalledInfo res) {
PackageParser.Package newPackage = null;
boolean updatedSettings = false;
- int parseFlags = PackageManager.REPLACE_EXISTING_PACKAGE |
+ int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING |
PackageParser.PARSE_IS_SYSTEM;
String packageName = deletedPackage.packageName;
res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
@@ -3501,7 +3528,8 @@
destResourceFile, pkg,
newPackage,
true,
- forwardLocked,
+ forwardLocked,
+ installerPackageName,
res);
updatedSettings = true;
}
@@ -3528,6 +3556,8 @@
synchronized(mPackages) {
if(updatedSettings) {
mSettings.enableSystemPackageLP(packageName);
+ mSettings.setInstallerPackageName(packageName,
+ oldPkgSetting.installerPackageName);
}
mSettings.writeLP();
}
@@ -3541,7 +3571,7 @@
PackageParser.Package newPackage,
boolean replacingExistingPackage,
boolean forwardLocked,
- PackageInstalledInfo res) {
+ String installerPackageName, PackageInstalledInfo res) {
synchronized (mPackages) {
//write settings. the installStatus will be incomplete at this stage.
//note that the new package setting would have already been
@@ -3588,6 +3618,7 @@
res.uid = newPackage.applicationInfo.uid;
res.pkg = newPackage;
mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
+ mSettings.setInstallerPackageName(pkgName, installerPackageName);
res.returnCode = PackageManager.INSTALL_SUCCEEDED;
//to update install status
mSettings.writeLP();
@@ -3595,7 +3626,7 @@
}
private PackageInstalledInfo installPackageLI(Uri pPackageURI,
- int pFlags, boolean newInstall) {
+ int pFlags, boolean newInstall, String installerPackageName) {
File tmpPackageFile = null;
String pkgName = null;
boolean forwardLocked = false;
@@ -3666,13 +3697,13 @@
res.name = pkgName;
//initialize some variables before installing pkg
final String pkgFileName = pkgName + ".apk";
- final File destDir = ((pFlags&PackageManager.FORWARD_LOCK_PACKAGE) != 0)
+ final File destDir = ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0)
? mDrmAppPrivateInstallDir
: mAppInstallDir;
final File destPackageFile = new File(destDir, pkgFileName);
final String destFilePath = destPackageFile.getAbsolutePath();
File destResourceFile;
- if ((pFlags&PackageManager.FORWARD_LOCK_PACKAGE) != 0) {
+ if ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0) {
final String publicZipFileName = pkgName + ".zip";
destResourceFile = new File(mAppInstallDir, publicZipFileName);
forwardLocked = true;
@@ -3684,13 +3715,19 @@
parseFlags |= mDefParseFlags;
PackageParser pp = new PackageParser(tmpPackageFile.getPath());
pp.setSeparateProcesses(mSeparateProcesses);
- pp.setSdkVersion(mSdkVersion);
+ pp.setSdkVersion(mSdkVersion, mSdkCodename);
final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
destPackageFile.getAbsolutePath(), mMetrics, parseFlags);
if (pkg == null) {
res.returnCode = pp.getParseError();
break main_flow;
}
+ if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
+ if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
+ res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
+ break main_flow;
+ }
+ }
if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
res.returnCode = pp.getParseError();
break main_flow;
@@ -3698,7 +3735,7 @@
synchronized (mPackages) {
//check if installing already existing package
- if ((pFlags&PackageManager.REPLACE_EXISTING_PACKAGE) != 0
+ if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
&& mPackages.containsKey(pkgName)) {
replacingExistingPackage = true;
}
@@ -3708,13 +3745,13 @@
replacePackageLI(pkgName,
tmpPackageFile,
destFilePath, destPackageFile, destResourceFile,
- pkg, forwardLocked, newInstall,
+ pkg, forwardLocked, newInstall, installerPackageName,
res);
} else {
installNewPackageLI(pkgName,
tmpPackageFile,
destFilePath, destPackageFile, destResourceFile,
- pkg, forwardLocked, newInstall,
+ pkg, forwardLocked, newInstall, installerPackageName,
res);
}
} finally {
@@ -3994,7 +4031,7 @@
* Tries to delete system package.
*/
private boolean deleteSystemPackageLI(PackageParser.Package p,
- boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
+ int flags, PackageRemovedInfo outInfo) {
ApplicationInfo applicationInfo = p.applicationInfo;
//applicable for non-partially installed applications only
if (applicationInfo == null) {
@@ -4016,6 +4053,19 @@
}
// Delete the updated package
outInfo.isRemovedPackageSystemUpdate = true;
+ boolean deleteCodeAndResources = false;
+ if (ps.versionCode < p.mVersionCode) {
+ // Delete code and resources for downgrades
+ deleteCodeAndResources = true;
+ if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
+ flags &= ~PackageManager.DONT_DELETE_DATA;
+ }
+ } else {
+ // Preserve data by setting flag
+ if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
+ flags |= PackageManager.DONT_DELETE_DATA;
+ }
+ }
boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
if (!ret) {
return false;
@@ -4039,6 +4089,28 @@
return true;
}
+ private void deletePackageResourcesLI(String packageName,
+ String sourceDir, String publicSourceDir) {
+ File sourceFile = new File(sourceDir);
+ if (!sourceFile.exists()) {
+ Log.w(TAG, "Package source " + sourceDir + " does not exist.");
+ }
+ // Delete application's code and resources
+ sourceFile.delete();
+ final File publicSourceFile = new File(publicSourceDir);
+ if (publicSourceFile.exists()) {
+ publicSourceFile.delete();
+ }
+ if (mInstaller != null) {
+ int retCode = mInstaller.rmdex(sourceFile.toString());
+ if (retCode < 0) {
+ Log.w(TAG, "Couldn't remove dex file for package: "
+ + packageName + " at location " + sourceFile.toString() + ", retcode=" + retCode);
+ // we don't consider this to be a failure of the core package deletion
+ }
+ }
+ }
+
private boolean deleteInstalledPackageLI(PackageParser.Package p,
boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
ApplicationInfo applicationInfo = p.applicationInfo;
@@ -4046,11 +4118,6 @@
Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
return false;
}
- // Delete application's source directory
- File sourceFile = new File(applicationInfo.sourceDir);
- if (!sourceFile.exists()) {
- Log.w(TAG, "Package source " + applicationInfo.sourceDir + " does not exist.");
- }
outInfo.uid = applicationInfo.uid;
// Delete package data from internal structures and also remove data if flag is set
@@ -4058,19 +4125,8 @@
// Delete application code and resources
if (deleteCodeAndResources) {
- sourceFile.delete();
- final File publicSourceFile = new File(applicationInfo.publicSourceDir);
- if (publicSourceFile.exists()) {
- publicSourceFile.delete();
- }
- if (mInstaller != null) {
- int retCode = mInstaller.rmdex(sourceFile.toString());
- if (retCode < 0) {
- Log.w(TAG, "Couldn't remove dex file for package: "
- + p.packageName + " at location " + sourceFile.toString() + ", retcode=" + retCode);
- // we don't consider this to be a failure of the core package deletion
- }
- }
+ deletePackageResourcesLI(applicationInfo.packageName,
+ applicationInfo.sourceDir, applicationInfo.publicSourceDir);
}
return true;
}
@@ -4118,7 +4174,7 @@
Log.i(TAG, "Removing system package:"+p.packageName);
// When an updated system application is deleted we delete the existing resources as well and
// fall back to existing code in system partition
- return deleteSystemPackageLI(p, true, flags, outInfo);
+ return deleteSystemPackageLI(p, flags, outInfo);
}
Log.i(TAG, "Removing non-system package:"+p.packageName);
return deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
@@ -4513,6 +4569,16 @@
}
}
+ public String getInstallerPackageName(String packageName) {
+ synchronized (mPackages) {
+ PackageSetting pkg = mSettings.mPackages.get(packageName);
+ if (pkg == null) {
+ throw new IllegalArgumentException("Unknown package: " + packageName);
+ }
+ return pkg.installerPackageName;
+ }
+ }
+
public int getApplicationEnabledSetting(String appPackageName) {
synchronized (mPackages) {
PackageSetting pkg = mSettings.mPackages.get(appPackageName);
@@ -4578,80 +4644,83 @@
return;
}
- Printer printer = new PrintWriterPrinter(pw);
synchronized (mPackages) {
pw.println("Activity Resolver Table:");
- mActivities.dump(printer, " ");
+ mActivities.dump(pw, " ");
pw.println(" ");
pw.println("Receiver Resolver Table:");
- mReceivers.dump(printer, " ");
+ mReceivers.dump(pw, " ");
pw.println(" ");
pw.println("Service Resolver Table:");
- mServices.dump(printer, " ");
+ mServices.dump(pw, " ");
pw.println(" ");
pw.println("Preferred Activities:");
- mSettings.mPreferredActivities.dump(printer, " ");
+ mSettings.mPreferredActivities.dump(pw, " ");
pw.println(" ");
pw.println("Preferred Packages:");
{
for (PackageSetting ps : mSettings.mPreferredPackages) {
- pw.println(" " + ps.name);
+ pw.print(" "); pw.println(ps.name);
}
}
pw.println(" ");
pw.println("Permissions:");
{
for (BasePermission p : mSettings.mPermissions.values()) {
- pw.println(" Permission [" + p.name + "] ("
- + Integer.toHexString(System.identityHashCode(p))
- + "):");
- pw.println(" sourcePackage=" + p.sourcePackage);
- pw.println(" uid=" + p.uid
- + " gids=" + arrayToString(p.gids)
- + " type=" + p.type);
+ pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
+ pw.print(Integer.toHexString(System.identityHashCode(p)));
+ pw.println("):");
+ pw.print(" sourcePackage="); pw.println(p.sourcePackage);
+ pw.print(" uid="); pw.print(p.uid);
+ pw.print(" gids="); pw.print(arrayToString(p.gids));
+ pw.print(" type="); pw.println(p.type);
}
}
pw.println(" ");
pw.println("Packages:");
{
for (PackageSetting ps : mSettings.mPackages.values()) {
- pw.println(" Package [" + ps.name + "] ("
- + Integer.toHexString(System.identityHashCode(ps))
- + "):");
- pw.println(" userId=" + ps.userId
- + " gids=" + arrayToString(ps.gids));
- pw.println(" sharedUser=" + ps.sharedUser);
- pw.println(" pkg=" + ps.pkg);
- pw.println(" codePath=" + ps.codePathString);
- pw.println(" resourcePath=" + ps.resourcePathString);
+ pw.print(" Package ["); pw.print(ps.name); pw.print("] (");
+ pw.print(Integer.toHexString(System.identityHashCode(ps)));
+ pw.println("):");
+ pw.print(" userId="); pw.print(ps.userId);
+ pw.print(" gids="); pw.println(arrayToString(ps.gids));
+ pw.print(" sharedUser="); pw.println(ps.sharedUser);
+ pw.print(" pkg="); pw.println(ps.pkg);
+ pw.print(" codePath="); pw.println(ps.codePathString);
+ pw.print(" resourcePath="); pw.println(ps.resourcePathString);
if (ps.pkg != null) {
- pw.println(" dataDir=" + ps.pkg.applicationInfo.dataDir);
+ pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
}
- pw.println(" timeStamp=" + ps.getTimeStampStr());
- pw.println(" signatures=" + ps.signatures);
- pw.println(" permissionsFixed=" + ps.permissionsFixed
- + " pkgFlags=0x" + Integer.toHexString(ps.pkgFlags)
- + " installStatus=" + ps.installStatus
- + " enabled=" + ps.enabled);
+ pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
+ pw.print(" signatures="); pw.println(ps.signatures);
+ pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
+ pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
+ pw.print(" installStatus="); pw.print(ps.installStatus);
+ pw.print(" enabled="); pw.println(ps.enabled);
if (ps.disabledComponents.size() > 0) {
pw.println(" disabledComponents:");
for (String s : ps.disabledComponents) {
- pw.println(" " + s);
+ pw.print(" "); pw.println(s);
}
}
if (ps.enabledComponents.size() > 0) {
pw.println(" enabledComponents:");
for (String s : ps.enabledComponents) {
- pw.println(" " + s);
+ pw.print(" "); pw.println(s);
}
}
- pw.println(" grantedPermissions:");
- for (String s : ps.grantedPermissions) {
- pw.println(" " + s);
+ if (ps.grantedPermissions.size() > 0) {
+ pw.println(" grantedPermissions:");
+ for (String s : ps.grantedPermissions) {
+ pw.print(" "); pw.println(s);
+ }
}
- pw.println(" loadedPermissions:");
- for (String s : ps.loadedPermissions) {
- pw.println(" " + s);
+ if (ps.loadedPermissions.size() > 0) {
+ pw.println(" loadedPermissions:");
+ for (String s : ps.loadedPermissions) {
+ pw.print(" "); pw.println(s);
+ }
}
}
}
@@ -4659,18 +4728,18 @@
pw.println("Shared Users:");
{
for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
- pw.println(" SharedUser [" + su.name + "] ("
- + Integer.toHexString(System.identityHashCode(su))
- + "):");
- pw.println(" userId=" + su.userId
- + " gids=" + arrayToString(su.gids));
+ pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
+ pw.print(Integer.toHexString(System.identityHashCode(su)));
+ pw.println("):");
+ pw.print(" userId="); pw.print(su.userId);
+ pw.print(" gids="); pw.println(arrayToString(su.gids));
pw.println(" grantedPermissions:");
for (String s : su.grantedPermissions) {
- pw.println(" " + s);
+ pw.print(" "); pw.println(s);
}
pw.println(" loadedPermissions:");
for (String s : su.loadedPermissions) {
- pw.println(" " + s);
+ pw.print(" "); pw.println(s);
}
}
}
@@ -5147,6 +5216,7 @@
final String resourcePathString;
private long timeStamp;
private String timeStampString = "0";
+ final int versionCode;
PackageSignatures signatures = new PackageSignatures();
@@ -5158,17 +5228,29 @@
HashSet<String> enabledComponents = new HashSet<String>(0);
int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
int installStatus = PKG_INSTALL_COMPLETE;
+
+ /* package name of the app that installed this package */
+ String installerPackageName;
PackageSettingBase(String name, File codePath, File resourcePath,
- int pkgFlags) {
+ int pVersionCode, int pkgFlags) {
super(pkgFlags);
this.name = name;
this.codePath = codePath;
this.codePathString = codePath.toString();
this.resourcePath = resourcePath;
this.resourcePathString = resourcePath.toString();
+ this.versionCode = pVersionCode;
}
+ public void setInstallerPackageName(String packageName) {
+ installerPackageName = packageName;
+ }
+
+ String getInstallerPackageName() {
+ return installerPackageName;
+ }
+
public void setInstallStatus(int newStatus) {
installStatus = newStatus;
}
@@ -5247,8 +5329,8 @@
SharedUserSetting sharedUser;
PackageSetting(String name, File codePath, File resourcePath,
- int pkgFlags) {
- super(name, codePath, resourcePath, pkgFlags);
+ int pVersionCode, int pkgFlags) {
+ super(name, codePath, resourcePath, pVersionCode, pkgFlags);
}
@Override
@@ -5302,16 +5384,19 @@
private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
new IntentResolver<PreferredActivity, PreferredActivity>() {
@Override
- protected void dumpFilter(Printer out, String prefix,
+ protected void dumpFilter(PrintWriter out, String prefix,
PreferredActivity filter) {
- out.println(prefix
- + Integer.toHexString(System.identityHashCode(filter))
- + " " + filter.mActivity.flattenToShortString()
- + " match=0x" + Integer.toHexString(filter.mMatch));
+ out.print(prefix); out.print(
+ Integer.toHexString(System.identityHashCode(filter)));
+ out.print(' ');
+ out.print(filter.mActivity.flattenToShortString());
+ out.print(" match=0x");
+ out.println( Integer.toHexString(filter.mMatch));
if (filter.mSetComponents != null) {
- out.println(prefix + " Selected from:");
+ out.print(prefix); out.println(" Selected from:");
for (int i=0; i<filter.mSetComponents.length; i++) {
- out.println(prefix + " " + filter.mSetComponents[i]);
+ out.print(prefix); out.print(" ");
+ out.println(filter.mSetComponents[i]);
}
}
}
@@ -5343,8 +5428,8 @@
final int sharedId;
PendingPackage(String name, File codePath, File resourcePath,
- int sharedId, int pkgFlags) {
- super(name, codePath, resourcePath, pkgFlags);
+ int sharedId, int pVersionCode, int pkgFlags) {
+ super(name, codePath, resourcePath, pVersionCode, pkgFlags);
this.sharedId = sharedId;
}
}
@@ -5368,7 +5453,7 @@
int pkgFlags, boolean create, boolean add) {
final String name = pkg.packageName;
PackageSetting p = getPackageLP(name, sharedUser, codePath,
- resourcePath, pkgFlags, create, add);
+ resourcePath, pkg.mVersionCode, pkgFlags, create, add);
if (p != null) {
p.pkg = pkg;
@@ -5376,12 +5461,15 @@
return p;
}
- PackageSetting peekPackageLP(String name, String codePath) {
+ PackageSetting peekPackageLP(String name) {
+ return mPackages.get(name);
+ /*
PackageSetting p = mPackages.get(name);
if (p != null && p.codePath.getPath().equals(codePath)) {
return p;
}
return null;
+ */
}
void setInstallStatus(String pkgName, int status) {
@@ -5393,6 +5481,19 @@
}
}
+ void setInstallerPackageName(String pkgName,
+ String installerPkgName) {
+ PackageSetting p = mPackages.get(pkgName);
+ if(p != null) {
+ p.setInstallerPackageName(installerPkgName);
+ }
+ }
+
+ String getInstallerPackageName(String pkgName) {
+ PackageSetting p = mPackages.get(pkgName);
+ return (p == null) ? null : p.getInstallerPackageName();
+ }
+
int getInstallStatus(String pkgName) {
PackageSetting p = mPackages.get(pkgName);
if(p != null) {
@@ -5453,13 +5554,13 @@
p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
PackageSetting ret = addPackageLP(name, p.codePath,
- p.resourcePath, p.userId, p.pkgFlags);
+ p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
mDisabledSysPackages.remove(name);
return ret;
}
PackageSetting addPackageLP(String name, File codePath,
- File resourcePath, int uid, int pkgFlags) {
+ File resourcePath, int uid, int vc, int pkgFlags) {
PackageSetting p = mPackages.get(name);
if (p != null) {
if (p.userId == uid) {
@@ -5469,7 +5570,7 @@
"Adding duplicate package, keeping first: " + name);
return null;
}
- p = new PackageSetting(name, codePath, resourcePath, pkgFlags);
+ p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
p.userId = uid;
if (addUserIdLP(uid, p, name)) {
mPackages.put(name, p);
@@ -5499,7 +5600,7 @@
private PackageSetting getPackageLP(String name,
SharedUserSetting sharedUser, File codePath, File resourcePath,
- int pkgFlags, boolean create, boolean add) {
+ int vc, int pkgFlags, boolean create, boolean add) {
PackageSetting p = mPackages.get(name);
if (p != null) {
if (!p.codePath.equals(codePath)) {
@@ -5541,7 +5642,7 @@
if (!create) {
return null;
}
- p = new PackageSetting(name, codePath, resourcePath, pkgFlags);
+ p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
p.setTimeStamp(codePath.lastModified());
if (sharedUser != null) {
p.userId = sharedUser.userId;
@@ -5808,6 +5909,7 @@
serializer.attribute(null, "name", pkg.name);
serializer.attribute(null, "codePath", pkg.codePathString);
serializer.attribute(null, "ts", pkg.getTimeStampStr());
+ serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
if (!pkg.resourcePathString.equals(pkg.codePathString)) {
serializer.attribute(null, "resourcePath", pkg.resourcePathString);
}
@@ -5851,6 +5953,7 @@
(pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
? "true" : "false");
serializer.attribute(null, "ts", pkg.getTimeStampStr());
+ serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
if (pkg.sharedUser == null) {
serializer.attribute(null, "userId",
Integer.toString(pkg.userId));
@@ -5866,6 +5969,9 @@
if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
serializer.attribute(null, "installStatus", "false");
}
+ if (pkg.installerPackageName != null) {
+ serializer.attribute(null, "installer", pkg.installerPackageName);
+ }
pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
serializer.startTag(null, "perms");
@@ -5900,6 +6006,7 @@
}
serializer.endTag(null, "enabled-components");
}
+
serializer.endTag(null, "package");
}
@@ -6042,7 +6149,7 @@
if (idObj != null && idObj instanceof SharedUserSetting) {
PackageSetting p = getPackageLP(pp.name,
(SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
- pp.pkgFlags, true, true);
+ pp.versionCode, pp.pkgFlags, true, true);
if (p == null) {
Log.w(TAG, "Unable to create application package for "
+ pp.name);
@@ -6161,12 +6268,20 @@
if(resourcePathStr == null) {
resourcePathStr = codePathStr;
}
+ String version = parser.getAttributeValue(null, "version");
+ int versionCode = 0;
+ if (version != null) {
+ try {
+ versionCode = Integer.parseInt(version);
+ } catch (NumberFormatException e) {
+ }
+ }
int pkgFlags = 0;
pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
PackageSetting ps = new PackageSetting(name,
new File(codePathStr),
- new File(resourcePathStr), pkgFlags);
+ new File(resourcePathStr), versionCode, pkgFlags);
String timeStampStr = parser.getAttributeValue(null, "ts");
if (timeStampStr != null) {
try {
@@ -6213,17 +6328,28 @@
String codePathStr = null;
String resourcePathStr = null;
String systemStr = null;
+ String installerPackageName = null;
int pkgFlags = 0;
String timeStampStr;
long timeStamp = 0;
PackageSettingBase packageSetting = null;
+ String version = null;
+ int versionCode = 0;
try {
name = parser.getAttributeValue(null, "name");
idStr = parser.getAttributeValue(null, "userId");
sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
codePathStr = parser.getAttributeValue(null, "codePath");
resourcePathStr = parser.getAttributeValue(null, "resourcePath");
+ version = parser.getAttributeValue(null, "version");
+ if (version != null) {
+ try {
+ versionCode = Integer.parseInt(version);
+ } catch (NumberFormatException e) {
+ }
+ }
systemStr = parser.getAttributeValue(null, "system");
+ installerPackageName = parser.getAttributeValue(null, "installer");
if (systemStr != null) {
if ("true".equals(systemStr)) {
pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
@@ -6256,7 +6382,7 @@
+ parser.getPositionDescription());
} else if (userId > 0) {
packageSetting = addPackageLP(name.intern(), new File(codePathStr),
- new File(resourcePathStr), userId, pkgFlags);
+ new File(resourcePathStr), userId, versionCode, pkgFlags);
if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
+ ": userId=" + userId + " pkg=" + packageSetting);
if (packageSetting == null) {
@@ -6272,7 +6398,7 @@
? Integer.parseInt(sharedIdStr) : 0;
if (userId > 0) {
packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
- new File(resourcePathStr), userId, pkgFlags);
+ new File(resourcePathStr), userId, versionCode, pkgFlags);
packageSetting.setTimeStamp(timeStamp, timeStampStr);
mPendingPackages.add((PendingPackage) packageSetting);
if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
@@ -6297,6 +6423,7 @@
+ parser.getPositionDescription());
}
if (packageSetting != null) {
+ packageSetting.installerPackageName = installerPackageName;
final String enabledStr = parser.getAttributeValue(null, "enabled");
if (enabledStr != null) {
if (enabledStr.equalsIgnoreCase("true")) {
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 9c6e9dc..c5ea5fa9 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -496,8 +496,10 @@
}
public void acquireWakeLock(int flags, IBinder lock, String tag) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
int uid = Binder.getCallingUid();
+ if (uid != Process.myUid()) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
+ }
long ident = Binder.clearCallingIdentity();
try {
synchronized (mLocks) {
@@ -554,14 +556,14 @@
// by the current state so we never turn it more on than
// it already is.
if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
- reactivateWakeLocksLocked();
+ int oldWakeLockState = mWakeLockState;
+ mWakeLockState = mLocks.reactivateScreenLocksLocked();
if (mSpew) {
Log.d(TAG, "wakeup here mUserState=0x" + Integer.toHexString(mUserState)
- + " mLocks.gatherState()=0x"
- + Integer.toHexString(mLocks.gatherState())
- + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState));
+ + " mWakeLockState=0x"
+ + Integer.toHexString(mWakeLockState)
+ + " previous wakeLockState=0x" + Integer.toHexString(oldWakeLockState));
}
- mWakeLockState = mLocks.gatherState();
} else {
if (mSpew) {
Log.d(TAG, "here mUserState=0x" + Integer.toHexString(mUserState)
@@ -598,7 +600,10 @@
}
public void releaseWakeLock(IBinder lock) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
+ int uid = Binder.getCallingUid();
+ if (uid != Process.myUid()) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
+ }
synchronized (mLocks) {
releaseWakeLockLocked(lock, false);
@@ -653,17 +658,6 @@
}
}
- private void reactivateWakeLocksLocked()
- {
- int N = mLocks.size();
- for (int i=0; i<N; i++) {
- WakeLock wl = mLocks.get(i);
- if (isScreenLock(wl.flags)) {
- mLocks.get(i).activated = true;
- }
- }
- }
-
private class PokeLock implements IBinder.DeathRecipient
{
PokeLock(int p, IBinder b, String t) {
@@ -1752,8 +1746,7 @@
Binder.restoreCallingIdentity(ident);
}
- reactivateWakeLocksLocked();
- mWakeLockState = mLocks.gatherState();
+ mWakeLockState = mLocks.reactivateScreenLocksLocked();
setPowerState(mUserState | mWakeLockState, noChangeLights, true);
setTimeoutLocked(time, SCREEN_BRIGHT);
}
@@ -1944,6 +1937,20 @@
}
return result;
}
+
+ int reactivateScreenLocksLocked()
+ {
+ int result = 0;
+ int N = this.size();
+ for (int i=0; i<N; i++) {
+ WakeLock wl = this.get(i);
+ if (isScreenLock(wl.flags)) {
+ wl.activated = true;
+ result |= wl.minState;
+ }
+ }
+ return result;
+ }
}
void setPolicy(WindowManagerPolicy p) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 1f508a6..8b7260b 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -306,6 +306,13 @@
}
try {
+ Log.i(TAG, "Starting Backup Service");
+ ServiceManager.addService(Context.BACKUP_SERVICE, new BackupManagerService(context));
+ } catch (Throwable e) {
+ Log.e(TAG, "Failure starting Backup Service", e);
+ }
+
+ try {
Log.i(TAG, "Starting AppWidget Service");
appWidget = new AppWidgetService(context);
ServiceManager.addService(Context.APPWIDGET_SERVICE, appWidget);
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 54e77f0..348f0a1 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -96,6 +96,11 @@
private int mScanLocksAcquired;
private int mScanLocksReleased;
+ private final List<WifiMulticaster> mMulticasters =
+ new ArrayList<WifiMulticaster>();
+ private int mMulticastEnabled;
+ private int mMulticastDisabled;
+
private final IBatteryStats mBatteryStats;
/**
@@ -165,7 +170,6 @@
* Character buffer used to parse scan results (optimization)
*/
private static final int SCAN_RESULT_BUFFER_SIZE = 512;
- private char[] mScanResultBuffer;
private boolean mNeedReconfig;
/*
@@ -204,8 +208,6 @@
}
};
- mScanResultBuffer = new char [SCAN_RESULT_BUFFER_SIZE];
-
HandlerThread wifiThread = new HandlerThread("WifiService");
wifiThread.start();
mWifiHandler = new WifiHandler(wifiThread.getLooper());
@@ -1217,61 +1219,13 @@
lineBeg = lineEnd + 1;
continue;
}
- int lineLen = lineEnd - lineBeg;
- if (0 < lineLen && lineLen <= SCAN_RESULT_BUFFER_SIZE) {
- int scanResultLevel = 0;
- /*
- * At most one thread should have access to the buffer at a time!
- */
- synchronized(mScanResultBuffer) {
- boolean parsingScanResultLevel = false;
- for (int i = lineBeg; i < lineEnd; ++i) {
- char ch = reply.charAt(i);
- /*
- * Assume that the signal level starts with a '-'
- */
- if (ch == '-') {
- /*
- * Skip whatever instances of '-' we may have
- * after we parse the signal level
- */
- parsingScanResultLevel = (scanResultLevel == 0);
- } else if (parsingScanResultLevel) {
- int digit = Character.digit(ch, 10);
- if (0 <= digit) {
- scanResultLevel =
- 10 * scanResultLevel + digit;
- /*
- * Replace the signal level number in
- * the string with 0's for caching
- */
- ch = '0';
- } else {
- /*
- * Reset the flag if we meet a non-digit
- * character
- */
- parsingScanResultLevel = false;
- }
- }
- mScanResultBuffer[i - lineBeg] = ch;
- }
- if (scanResultLevel != 0) {
- ScanResult scanResult = parseScanResult(
- new String(mScanResultBuffer, 0, lineLen));
- if (scanResult != null) {
- scanResult.level = -scanResultLevel;
- scanList.add(scanResult);
- }
- } else if (DBG) {
- Log.w(TAG,
- "ScanResult.level=0: misformatted scan result?");
- }
- }
- } else if (0 < lineLen) {
- if (DBG) {
- Log.w(TAG, "Scan result line is too long: " +
- (lineEnd - lineBeg) + ", skipping the line!");
+ if (lineEnd > lineBeg) {
+ String line = reply.substring(lineBeg, lineEnd);
+ ScanResult scanResult = parseScanResult(line);
+ if (scanResult != null) {
+ scanList.add(scanResult);
+ } else if (DBG) {
+ Log.w(TAG, "misformatted scan result for: " + line);
}
}
lineBeg = lineEnd + 1;
@@ -1294,21 +1248,29 @@
* must synchronized here!
*/
synchronized (mScanResultCache) {
- scanResult = mScanResultCache.get(line);
- if (scanResult == null) {
- String[] result = scanResultPattern.split(line);
- if (3 <= result.length && result.length <= 5) {
- // bssid | frequency | level | flags | ssid
- int frequency;
- int level;
- try {
- frequency = Integer.parseInt(result[1]);
- level = Integer.parseInt(result[2]);
- } catch (NumberFormatException e) {
- frequency = 0;
- level = 0;
- }
+ String[] result = scanResultPattern.split(line);
+ if (3 <= result.length && result.length <= 5) {
+ String bssid = result[0];
+ // bssid | frequency | level | flags | ssid
+ int frequency;
+ int level;
+ try {
+ frequency = Integer.parseInt(result[1]);
+ level = Integer.parseInt(result[2]);
+ /* some implementations avoid negative values by adding 256
+ * so we need to adjust for that here.
+ */
+ if (level > 0) level -= 256;
+ } catch (NumberFormatException e) {
+ frequency = 0;
+ level = 0;
+ }
+ // bssid is the hash key
+ scanResult = mScanResultCache.get(bssid);
+ if (scanResult != null) {
+ scanResult.level = level;
+ } else {
/*
* The formatting of the results returned by
* wpa_supplicant is intended to make the fields
@@ -1341,13 +1303,13 @@
if (0 < ssid.trim().length()) {
scanResult =
new ScanResult(
- ssid, result[0], flags, level, frequency);
- mScanResultCache.put(line, scanResult);
+ ssid, bssid, flags, level, frequency);
+ mScanResultCache.put(bssid, scanResult);
}
- } else {
- Log.w(TAG, "Misformatted scan result text with " +
- result.length + " fields: " + line);
}
+ } else {
+ Log.w(TAG, "Misformatted scan result text with " +
+ result.length + " fields: " + line);
}
}
}
@@ -1770,21 +1732,9 @@
}
}
- private class WifiLock implements IBinder.DeathRecipient {
- String mTag;
- int mLockMode;
- IBinder mBinder;
-
+ private class WifiLock extends WifiDeathRecipient {
WifiLock(int lockMode, String tag, IBinder binder) {
- super();
- mTag = tag;
- mLockMode = lockMode;
- mBinder = binder;
- try {
- mBinder.linkToDeath(this, 0);
- } catch (RemoteException e) {
- binderDied();
- }
+ super(lockMode, tag, binder);
}
public void binderDied() {
@@ -1794,7 +1744,7 @@
}
public String toString() {
- return "WifiLock{" + mTag + " type=" + mLockMode + " binder=" + mBinder + "}";
+ return "WifiLock{" + mTag + " type=" + mMode + " binder=" + mBinder + "}";
}
}
@@ -1814,7 +1764,7 @@
return WifiManager.WIFI_MODE_FULL;
}
for (WifiLock l : mList) {
- if (l.mLockMode == WifiManager.WIFI_MODE_FULL) {
+ if (l.mMode == WifiManager.WIFI_MODE_FULL) {
return WifiManager.WIFI_MODE_FULL;
}
}
@@ -1869,7 +1819,7 @@
int uid = Binder.getCallingUid();
long ident = Binder.clearCallingIdentity();
try {
- switch(wifiLock.mLockMode) {
+ switch(wifiLock.mMode) {
case WifiManager.WIFI_MODE_FULL:
++mFullLocksAcquired;
mBatteryStats.noteFullWifiLockAcquired(uid);
@@ -1905,7 +1855,7 @@
int uid = Binder.getCallingUid();
long ident = Binder.clearCallingIdentity();
try {
- switch(wifiLock.mLockMode) {
+ switch(wifiLock.mMode) {
case WifiManager.WIFI_MODE_FULL:
++mFullLocksReleased;
mBatteryStats.noteFullWifiLockReleased(uid);
@@ -1924,4 +1874,110 @@
updateWifiState();
return hadLock;
}
+
+ private abstract class WifiDeathRecipient
+ implements IBinder.DeathRecipient {
+ String mTag;
+ int mMode;
+ IBinder mBinder;
+
+ WifiDeathRecipient(int mode, String tag, IBinder binder) {
+ super();
+ mTag = tag;
+ mMode = mode;
+ mBinder = binder;
+ try {
+ mBinder.linkToDeath(this, 0);
+ } catch (RemoteException e) {
+ binderDied();
+ }
+ }
+ }
+
+ private class WifiMulticaster extends WifiDeathRecipient {
+ WifiMulticaster(String tag, IBinder binder) {
+ super(Binder.getCallingUid(), tag, binder);
+ }
+
+ public void binderDied() {
+ Log.e(TAG, "WifiMulticaster binderDied");
+ synchronized (mMulticasters) {
+ int i = mMulticasters.indexOf(this);
+ if (i != -1) {
+ removeMulticasterLocked(i, mMode);
+ }
+ }
+ }
+
+ public String toString() {
+ return "WifiMulticaster{" + mTag + " binder=" + mBinder + "}";
+ }
+
+ public int getUid() {
+ return mMode;
+ }
+ }
+
+ public void enableWifiMulticast(IBinder binder, String tag) {
+ enforceChangePermission();
+
+ synchronized (mMulticasters) {
+ mMulticastEnabled++;
+ mMulticasters.add(new WifiMulticaster(tag, binder));
+ // Note that we could call stopPacketFiltering only when
+ // our new size == 1 (first call), but this function won't
+ // be called often and by making the stopPacket call each
+ // time we're less fragile and self-healing.
+ WifiNative.stopPacketFiltering();
+ }
+
+ int uid = Binder.getCallingUid();
+ Long ident = Binder.clearCallingIdentity();
+ try {
+ mBatteryStats.noteWifiMulticastEnabled(uid);
+ } catch (RemoteException e) {
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ public void disableWifiMulticast() {
+ enforceChangePermission();
+
+ int uid = Binder.getCallingUid();
+ synchronized (mMulticasters) {
+ mMulticastDisabled++;
+ int size = mMulticasters.size();
+ for (int i = size - 1; i >= 0; i--) {
+ WifiMulticaster m = mMulticasters.get(i);
+ if ((m != null) && (m.getUid() == uid)) {
+ removeMulticasterLocked(i, uid);
+ }
+ }
+ }
+ }
+
+ private void removeMulticasterLocked(int i, int uid)
+ {
+ mMulticasters.remove(i);
+ if (mMulticasters.size() == 0) {
+ WifiNative.startPacketFiltering();
+ }
+
+ Long ident = Binder.clearCallingIdentity();
+ try {
+ mBatteryStats.noteWifiMulticastDisabled(uid);
+ } catch (RemoteException e) {
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ public boolean isWifiMulticastEnabled() {
+ enforceAccessPermission();
+
+ synchronized (mMulticasters) {
+ return (mMulticasters.size() > 0);
+ }
+ }
}
diff --git a/services/java/com/android/server/WifiWatchdogService.java b/services/java/com/android/server/WifiWatchdogService.java
index fe97b93..9443a95 100644
--- a/services/java/com/android/server/WifiWatchdogService.java
+++ b/services/java/com/android/server/WifiWatchdogService.java
@@ -75,14 +75,6 @@
private static final boolean V = false || Config.LOGV;
private static final boolean D = true || Config.LOGD;
- /*
- * When this was "net.dns1", sometimes the mobile data's DNS was seen
- * instead due to a race condition. All we really care about is the
- * DHCP-replied DNS server anyway.
- */
- /** The system property whose value provides the current DNS address. */
- private static final String SYSTEMPROPERTY_KEY_DNS = "dhcp.tiwlan0.dns1";
-
private Context mContext;
private ContentResolver mContentResolver;
private WifiStateTracker mWifiStateTracker;
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 0b1ddc8..3fa5baf 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -77,7 +77,6 @@
import android.os.SystemProperties;
import android.os.TokenWatcher;
import android.provider.Settings;
-import android.util.Config;
import android.util.EventLog;
import android.util.Log;
import android.util.SparseIntArray;
@@ -137,7 +136,7 @@
static final boolean PROFILE_ORIENTATION = false;
static final boolean BLUR = true;
- static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
+ static final boolean localLOGV = DEBUG;
static final int LOG_WM_NO_SURFACE_MEMORY = 31000;
@@ -180,6 +179,25 @@
static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
+ /** The minimum time between dispatching touch events. */
+ int mMinWaitTimeBetweenTouchEvents = 1000 / 35;
+
+ // Last touch event time
+ long mLastTouchEventTime = 0;
+
+ // Last touch event type
+ int mLastTouchEventType = OTHER_EVENT;
+
+ // Time to wait before calling useractivity again. This saves CPU usage
+ // when we get a flood of touch events.
+ static final int MIN_TIME_BETWEEN_USERACTIVITIES = 1000;
+
+ // Last time we call user activity
+ long mLastUserActivityCallTime = 0;
+
+ // Last time we updated battery stats
+ long mLastBatteryStatsCallTime = 0;
+
private static final String SYSTEM_SECURE = "ro.secure";
/**
@@ -2023,7 +2041,7 @@
wtoken.appFullscreen = fullscreen;
wtoken.requestedOrientation = requestedOrientation;
mAppTokens.add(addPos, wtoken);
- if (Config.LOGV) Log.v(TAG, "Adding new app token: " + wtoken);
+ if (localLOGV) Log.v(TAG, "Adding new app token: " + wtoken);
mTokenMap.put(token.asBinder(), wtoken);
mTokenList.add(wtoken);
@@ -2079,13 +2097,16 @@
int pos = mAppTokens.size() - 1;
int curGroup = 0;
int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+ boolean findingBehind = false;
boolean haveGroup = false;
boolean lastFullscreen = false;
while (pos >= 0) {
AppWindowToken wtoken = mAppTokens.get(pos);
pos--;
- // if we're about to tear down this window, don't use it for orientation
- if (!wtoken.hidden && wtoken.hiddenRequested) {
+ // if we're about to tear down this window and not seek for
+ // the behind activity, don't use it for orientation
+ if (!findingBehind
+ && (!wtoken.hidden && wtoken.hiddenRequested)) {
continue;
}
@@ -2109,10 +2130,12 @@
}
}
int or = wtoken.requestedOrientation;
- // If this application is fullscreen, then just take whatever
+ // If this application is fullscreen, and didn't explicitly say
+ // to use the orientation behind it, then just take whatever
// orientation it has and ignores whatever is under it.
lastFullscreen = wtoken.appFullscreen;
- if (lastFullscreen) {
+ if (lastFullscreen
+ && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
return or;
}
// If this application has requested an explicit orientation,
@@ -2124,6 +2147,7 @@
or == ActivityInfo.SCREEN_ORIENTATION_USER) {
return or;
}
+ findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
}
return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
}
@@ -3689,9 +3713,20 @@
// -------------------------------------------------------------
private final void wakeupIfNeeded(WindowState targetWin, int eventType) {
- if (targetWin == null ||
- targetWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
- mPowerManager.userActivity(SystemClock.uptimeMillis(), false, eventType);
+ long curTime = SystemClock.uptimeMillis();
+
+ if (eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT) {
+ if (mLastTouchEventType == eventType &&
+ (curTime - mLastUserActivityCallTime) < MIN_TIME_BETWEEN_USERACTIVITIES) {
+ return;
+ }
+ mLastUserActivityCallTime = curTime;
+ mLastTouchEventType = eventType;
+ }
+
+ if (targetWin == null
+ || targetWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
+ mPowerManager.userActivity(curTime, false, eventType, false);
}
}
@@ -3759,7 +3794,7 @@
// events in such a way, since this means the user is moving the
// pointer without actually pressing down. All other cases should
// be atypical, so let's log them.
- if (ev.getAction() != MotionEvent.ACTION_MOVE) {
+ if (action != MotionEvent.ACTION_MOVE) {
Log.w(TAG, "No window to dispatch pointer action " + ev.getAction());
}
if (qev != null) {
@@ -3846,7 +3881,39 @@
return false;
}
} //end if target
-
+
+ // TODO remove once we settle on a value or make it app specific
+ if (action == MotionEvent.ACTION_DOWN) {
+ int max_events_per_sec = 35;
+ try {
+ max_events_per_sec = Integer.parseInt(SystemProperties
+ .get("windowsmgr.max_events_per_sec"));
+ if (max_events_per_sec < 1) {
+ max_events_per_sec = 35;
+ }
+ } catch (NumberFormatException e) {
+ }
+ mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
+ }
+
+ /*
+ * Throttle events to minimize CPU usage when there's a flood of events
+ * e.g. constant contact with the screen
+ */
+ if (action == MotionEvent.ACTION_MOVE) {
+ long nextEventTime = mLastTouchEventTime + mMinWaitTimeBetweenTouchEvents;
+ long now = SystemClock.uptimeMillis();
+ if (now < nextEventTime) {
+ try {
+ Thread.sleep(nextEventTime - now);
+ } catch (InterruptedException e) {
+ }
+ mLastTouchEventTime = nextEventTime;
+ } else {
+ mLastTouchEventTime = now;
+ }
+ }
+
synchronized(mWindowMap) {
if (qev != null && action == MotionEvent.ACTION_MOVE) {
mKeyWaiter.bindTargetWindowLocked(target,
@@ -4801,14 +4868,11 @@
mPaused = true;
} else {
if (mLastWin == null) {
- if (Config.LOGI) Log.i(
- TAG, "Key dispatching not paused: no last window.");
+ Log.i(TAG, "Key dispatching not paused: no last window.");
} else if (mFinished) {
- if (Config.LOGI) Log.i(
- TAG, "Key dispatching not paused: finished last key.");
+ Log.i(TAG, "Key dispatching not paused: finished last key.");
} else {
- if (Config.LOGI) Log.i(
- TAG, "Key dispatching not paused: window in higher layer.");
+ Log.i(TAG, "Key dispatching not paused: window in higher layer.");
}
}
*/
@@ -4926,7 +4990,7 @@
}
if ((actions & WindowManagerPolicy.ACTION_POKE_USER_ACTIVITY) != 0) {
mPowerManager.userActivity(event.when, false,
- LocalPowerManager.BUTTON_EVENT);
+ LocalPowerManager.BUTTON_EVENT, false);
}
if ((actions & WindowManagerPolicy.ACTION_PASS_TO_USER) != 0) {
@@ -5086,11 +5150,17 @@
eventType = LocalPowerManager.OTHER_EVENT;
}
try {
- mBatteryStats.noteInputEvent();
+ long now = SystemClock.uptimeMillis();
+
+ if ((now - mLastBatteryStatsCallTime)
+ >= MIN_TIME_BETWEEN_USERACTIVITIES) {
+ mLastBatteryStatsCallTime = now;
+ mBatteryStats.noteInputEvent();
+ }
} catch (RemoteException e) {
// Ignore
}
- mPowerManager.userActivity(curTime, false, eventType);
+ mPowerManager.userActivity(curTime, false, eventType, false);
switch (ev.classType) {
case RawInputEvent.CLASS_KEYBOARD:
KeyEvent ke = (KeyEvent)ev.event;
@@ -5179,6 +5249,7 @@
final IInputContext mInputContext;
final int mUid;
final int mPid;
+ final String mStringName;
SurfaceSession mSurfaceSession;
int mNumWindow = 0;
boolean mClientDead = false;
@@ -5202,6 +5273,14 @@
mInputContext = inputContext;
mUid = Binder.getCallingUid();
mPid = Binder.getCallingPid();
+ StringBuilder sb = new StringBuilder();
+ sb.append("Session{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(" uid ");
+ sb.append(mUid);
+ sb.append("}");
+ mStringName = sb.toString();
+
synchronized (mWindowMap) {
if (mInputMethodManager == null && mHaveInputMethods) {
IBinder b = ServiceManager.getService(
@@ -5381,20 +5460,24 @@
}
void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + this);
- pw.println(prefix + "mNumWindow=" + mNumWindow
- + " mClientDead=" + mClientDead
- + " mSurfaceSession=" + mSurfaceSession);
- pw.println(prefix + "mPendingPointerWindow=" + mPendingPointerWindow
- + " mPendingPointerMove=" + mPendingPointerMove);
- pw.println(prefix + "mPendingTrackballWindow=" + mPendingTrackballWindow
- + " mPendingTrackballMove=" + mPendingTrackballMove);
+ pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
+ pw.print(" mClientDead="); pw.print(mClientDead);
+ pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
+ if (mPendingPointerWindow != null || mPendingPointerMove != null) {
+ pw.print(prefix);
+ pw.print("mPendingPointerWindow="); pw.print(mPendingPointerWindow);
+ pw.print(" mPendingPointerMove="); pw.println(mPendingPointerMove);
+ }
+ if (mPendingTrackballWindow != null || mPendingTrackballMove != null) {
+ pw.print(prefix);
+ pw.print("mPendingTrackballWindow="); pw.print(mPendingTrackballWindow);
+ pw.print(" mPendingTrackballMove="); pw.println(mPendingTrackballMove);
+ }
}
@Override
public String toString() {
- return "Session{"
- + Integer.toHexString(System.identityHashCode(this)) + "}";
+ return mStringName;
}
}
@@ -6462,67 +6545,114 @@
}
void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + this);
- pw.println(prefix + "mSession=" + mSession
- + " mClient=" + mClient.asBinder());
- pw.println(prefix + "mAttrs=" + mAttrs);
- pw.println(prefix + "mAttachedWindow=" + mAttachedWindow
- + " mLayoutAttached=" + mLayoutAttached
- + " mIsImWindow=" + mIsImWindow);
- pw.println(prefix + "mBaseLayer=" + mBaseLayer
- + " mSubLayer=" + mSubLayer
- + " mAnimLayer=" + mLayer + "+"
- + (mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
- : (mAppToken != null ? mAppToken.animLayerAdjustment : 0))
- + "=" + mAnimLayer
- + " mLastLayer=" + mLastLayer);
- pw.println(prefix + "mSurface=" + mSurface);
- pw.println(prefix + "mToken=" + mToken);
- pw.println(prefix + "mRootToken=" + mRootToken);
- pw.println(prefix + "mAppToken=" + mAppToken);
- pw.println(prefix + "mTargetAppToken=" + mTargetAppToken);
- pw.println(prefix + "mViewVisibility=0x" + Integer.toHexString(mViewVisibility)
- + " mPolicyVisibility=" + mPolicyVisibility
- + " (after=" + mPolicyVisibilityAfterAnim
- + ") mAttachedHidden=" + mAttachedHidden
- + " mLastHidden=" + mLastHidden
- + " mHaveFrame=" + mHaveFrame);
- pw.println(prefix + "Requested w=" + mRequestedWidth + " h=" + mRequestedHeight
- + " x=" + mReqXPos + " y=" + mReqYPos);
- pw.println(prefix + "mGivenContentInsets=" + mGivenContentInsets.toShortString()
- + " mGivenVisibleInsets=" + mGivenVisibleInsets.toShortString()
- + " mTouchableInsets=" + mTouchableInsets
- + " pending=" + mGivenInsetsPending);
- pw.println(prefix + "mShownFrame=" + mShownFrame.toShortString()
- + " last=" + mLastShownFrame.toShortString());
- pw.println(prefix + "mFrame=" + mFrame.toShortString()
- + " last=" + mLastFrame.toShortString());
- pw.println(prefix + "mContainingFrame=" + mContainingFrame.toShortString()
- + " mDisplayFrame=" + mDisplayFrame.toShortString());
- pw.println(prefix + "mContentFrame=" + mContentFrame.toShortString()
- + " mVisibleFrame=" + mVisibleFrame.toShortString());
- pw.println(prefix + "mContentInsets=" + mContentInsets.toShortString()
- + " last=" + mLastContentInsets.toShortString()
- + " mVisibleInsets=" + mVisibleInsets.toShortString()
- + " last=" + mLastVisibleInsets.toShortString());
- pw.println(prefix + "mShownAlpha=" + mShownAlpha
- + " mAlpha=" + mAlpha + " mLastAlpha=" + mLastAlpha);
- pw.println(prefix + "mAnimating=" + mAnimating
- + " mLocalAnimating=" + mLocalAnimating
- + " mAnimationIsEntrance=" + mAnimationIsEntrance
- + " mAnimation=" + mAnimation);
- pw.println(prefix + "XForm: has=" + mHasTransformation
- + " " + mTransformation.toShortString());
- pw.println(prefix + "mDrawPending=" + mDrawPending
- + " mCommitDrawPending=" + mCommitDrawPending
- + " mReadyToShow=" + mReadyToShow
- + " mHasDrawn=" + mHasDrawn);
- pw.println(prefix + "mExiting=" + mExiting
- + " mRemoveOnExit=" + mRemoveOnExit
- + " mDestroying=" + mDestroying
- + " mRemoved=" + mRemoved);
- pw.println(prefix + "mOrientationChanging=" + mOrientationChanging
- + " mAppFreezing=" + mAppFreezing);
+ StringBuilder sb = new StringBuilder(64);
+
+ pw.print(prefix); pw.print("mSession="); pw.print(mSession);
+ pw.print(" mClient="); pw.println(mClient.asBinder());
+ pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
+ if (mAttachedWindow != null || mLayoutAttached) {
+ pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
+ pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
+ }
+ if (mIsImWindow) {
+ pw.print(prefix); pw.print("mIsImWindow="); pw.println(mIsImWindow);
+ }
+ pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
+ pw.print(" mSubLayer="); pw.print(mSubLayer);
+ pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
+ pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
+ : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
+ pw.print("="); pw.print(mAnimLayer);
+ pw.print(" mLastLayer="); pw.println(mLastLayer);
+ if (mSurface != null) {
+ pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
+ }
+ pw.print(prefix); pw.print("mToken="); pw.println(mToken);
+ pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
+ if (mAppToken != null) {
+ pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
+ }
+ if (mTargetAppToken != null) {
+ pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
+ }
+ pw.print(prefix); pw.print("mViewVisibility=0x");
+ pw.print(Integer.toHexString(mViewVisibility));
+ pw.print(" mLastHidden="); pw.print(mLastHidden);
+ pw.print(" mHaveFrame="); pw.println(mHaveFrame);
+ if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
+ pw.print(prefix); pw.print("mPolicyVisibility=");
+ pw.print(mPolicyVisibility);
+ pw.print(" mPolicyVisibilityAfterAnim=");
+ pw.print(mPolicyVisibilityAfterAnim);
+ pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
+ }
+ pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
+ pw.print(" h="); pw.print(mRequestedHeight);
+ pw.print(" x="); pw.print(mReqXPos);
+ pw.print(" y="); pw.println(mReqYPos);
+ pw.print(prefix); pw.print("mGivenContentInsets=");
+ mGivenContentInsets.printShortString(pw);
+ pw.print(" mGivenVisibleInsets=");
+ mGivenVisibleInsets.printShortString(pw);
+ pw.println();
+ if (mTouchableInsets != 0 || mGivenInsetsPending) {
+ pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
+ pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
+ }
+ pw.print(prefix); pw.print("mShownFrame=");
+ mShownFrame.printShortString(pw);
+ pw.print(" last="); mLastShownFrame.printShortString(pw);
+ pw.println();
+ pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
+ pw.print(" last="); mLastFrame.printShortString(pw);
+ pw.println();
+ pw.print(prefix); pw.print("mContainingFrame=");
+ mContainingFrame.printShortString(pw);
+ pw.print(" mDisplayFrame=");
+ mDisplayFrame.printShortString(pw);
+ pw.println();
+ pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw);
+ pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw);
+ pw.println();
+ pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw);
+ pw.print(" last="); mLastContentInsets.printShortString(pw);
+ pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw);
+ pw.print(" last="); mLastVisibleInsets.printShortString(pw);
+ pw.println();
+ if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
+ pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
+ pw.print(" mAlpha="); pw.print(mAlpha);
+ pw.print(" mLastAlpha="); pw.println(mLastAlpha);
+ }
+ if (mAnimating || mLocalAnimating || mAnimationIsEntrance
+ || mAnimation != null) {
+ pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
+ pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
+ pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
+ pw.print(" mAnimation="); pw.println(mAnimation);
+ }
+ if (mHasTransformation || mHasLocalTransformation) {
+ pw.print(prefix); pw.print("XForm: has=");
+ pw.print(mHasTransformation);
+ pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
+ pw.print(" "); mTransformation.printShortString(pw);
+ pw.println();
+ }
+ pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
+ pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
+ pw.print(" mReadyToShow="); pw.print(mReadyToShow);
+ pw.print(" mHasDrawn="); pw.println(mHasDrawn);
+ if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
+ pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
+ pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
+ pw.print(" mDestroying="); pw.print(mDestroying);
+ pw.print(" mRemoved="); pw.println(mRemoved);
+ }
+ if (mOrientationChanging || mAppFreezing) {
+ pw.print(prefix); pw.print("mOrientationChanging=");
+ pw.print(mOrientationChanging);
+ pw.print(" mAppFreezing="); pw.println(mAppFreezing);
+ }
}
@Override
@@ -6548,6 +6678,9 @@
// not be removed when all windows are removed.
final boolean explicit;
+ // For printing.
+ String stringName;
+
// If this is an AppWindowToken, this is non-null.
AppWindowToken appWindowToken;
@@ -6570,18 +6703,23 @@
}
void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + this);
- pw.println(prefix + "token=" + token);
- pw.println(prefix + "windows=" + windows);
- pw.println(prefix + "windowType=" + windowType + " hidden=" + hidden
- + " hasVisible=" + hasVisible);
+ pw.print(prefix); pw.print("token="); pw.println(token);
+ pw.print(prefix); pw.print("windows="); pw.println(windows);
+ pw.print(prefix); pw.print("windowType="); pw.print(windowType);
+ pw.print(" hidden="); pw.print(hidden);
+ pw.print(" hasVisible="); pw.println(hasVisible);
}
@Override
public String toString() {
- return "WindowToken{"
- + Integer.toHexString(System.identityHashCode(this))
- + " token=" + token + "}";
+ if (stringName == null) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("WindowToken{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(" token="); sb.append(token); sb.append('}');
+ stringName = sb.toString();
+ }
+ return stringName;
}
};
@@ -6869,38 +7007,66 @@
void dump(PrintWriter pw, String prefix) {
super.dump(pw, prefix);
- pw.println(prefix + "app=" + (appToken != null));
- pw.println(prefix + "allAppWindows=" + allAppWindows);
- pw.println(prefix + "groupId=" + groupId
- + " requestedOrientation=" + requestedOrientation);
- pw.println(prefix + "hiddenRequested=" + hiddenRequested
- + " clientHidden=" + clientHidden
- + " willBeHidden=" + willBeHidden
- + " reportedVisible=" + reportedVisible);
- pw.println(prefix + "paused=" + paused
- + " freezingScreen=" + freezingScreen);
- pw.println(prefix + "numInterestingWindows=" + numInterestingWindows
- + " numDrawnWindows=" + numDrawnWindows
- + " inPendingTransaction=" + inPendingTransaction
- + " allDrawn=" + allDrawn);
- pw.println(prefix + "animating=" + animating
- + " animation=" + animation);
- pw.println(prefix + "animLayerAdjustment=" + animLayerAdjustment
- + " transformation=" + transformation.toShortString());
- pw.println(prefix + "startingData=" + startingData
- + " removed=" + removed
- + " firstWindowDrawn=" + firstWindowDrawn);
- pw.println(prefix + "startingWindow=" + startingWindow
- + " startingView=" + startingView
- + " startingDisplayed=" + startingDisplayed
- + " startingMoved" + startingMoved);
+ if (appToken != null) {
+ pw.print(prefix); pw.println("app=true");
+ }
+ if (allAppWindows.size() > 0) {
+ pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
+ }
+ pw.print(prefix); pw.print("groupId="); pw.print(groupId);
+ pw.print(" requestedOrientation="); pw.println(requestedOrientation);
+ pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
+ pw.print(" clientHidden="); pw.print(clientHidden);
+ pw.print(" willBeHidden="); pw.print(willBeHidden);
+ pw.print(" reportedVisible="); pw.println(reportedVisible);
+ if (paused || freezingScreen) {
+ pw.print(prefix); pw.print("paused="); pw.print(paused);
+ pw.print(" freezingScreen="); pw.println(freezingScreen);
+ }
+ if (numInterestingWindows != 0 || numDrawnWindows != 0
+ || inPendingTransaction || allDrawn) {
+ pw.print(prefix); pw.print("numInterestingWindows=");
+ pw.print(numInterestingWindows);
+ pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
+ pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
+ pw.print(" allDrawn="); pw.println(allDrawn);
+ }
+ if (animating || animation != null) {
+ pw.print(prefix); pw.print("animating="); pw.print(animating);
+ pw.print(" animation="); pw.println(animation);
+ }
+ if (animLayerAdjustment != 0) {
+ pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
+ }
+ if (hasTransformation) {
+ pw.print(prefix); pw.print("hasTransformation="); pw.print(hasTransformation);
+ pw.print(" transformation="); transformation.printShortString(pw);
+ pw.println();
+ }
+ if (startingData != null || removed || firstWindowDrawn) {
+ pw.print(prefix); pw.print("startingData="); pw.print(startingData);
+ pw.print(" removed="); pw.print(removed);
+ pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn);
+ }
+ if (startingWindow != null || startingView != null
+ || startingDisplayed || startingMoved) {
+ pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
+ pw.print(" startingView="); pw.print(startingView);
+ pw.print(" startingDisplayed="); pw.print(startingDisplayed);
+ pw.print(" startingMoved"); pw.println(startingMoved);
+ }
}
@Override
public String toString() {
- return "AppWindowToken{"
- + Integer.toHexString(System.identityHashCode(this))
- + " token=" + token + "}";
+ if (stringName == null) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("AppWindowToken{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(" token="); sb.append(token); sb.append('}');
+ stringName = sb.toString();
+ }
+ return stringName;
}
}
@@ -7423,7 +7589,7 @@
private boolean mInLayout = false;
private final void performLayoutAndPlaceSurfacesLocked() {
if (mInLayout) {
- if (Config.DEBUG) {
+ if (DEBUG) {
throw new RuntimeException("Recursive call!");
}
Log.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout");
@@ -8656,7 +8822,8 @@
pw.println("Current Window Manager state:");
for (int i=mWindows.size()-1; i>=0; i--) {
WindowState w = (WindowState)mWindows.get(i);
- pw.println(" Window #" + i + ":");
+ pw.print(" Window #"); pw.print(i); pw.print(' ');
+ pw.print(w); pw.println(":");
w.dump(pw, " ");
}
if (mInputMethodDialogs.size() > 0) {
@@ -8664,7 +8831,7 @@
pw.println(" Input method dialogs:");
for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
WindowState w = mInputMethodDialogs.get(i);
- pw.println(" IM Dialog #" + i + ": " + w);
+ pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
}
}
if (mPendingRemove.size() > 0) {
@@ -8672,7 +8839,8 @@
pw.println(" Remove pending for:");
for (int i=mPendingRemove.size()-1; i>=0; i--) {
WindowState w = mPendingRemove.get(i);
- pw.println(" Remove #" + i + ":");
+ pw.print(" Remove #"); pw.print(i); pw.print(' ');
+ pw.print(w); pw.println(":");
w.dump(pw, " ");
}
}
@@ -8681,7 +8849,8 @@
pw.println(" Windows force removing:");
for (int i=mForceRemoves.size()-1; i>=0; i--) {
WindowState w = mForceRemoves.get(i);
- pw.println(" Removing #" + i + ":");
+ pw.print(" Removing #"); pw.print(i); pw.print(' ');
+ pw.print(w); pw.println(":");
w.dump(pw, " ");
}
}
@@ -8690,7 +8859,8 @@
pw.println(" Windows waiting to destroy their surface:");
for (int i=mDestroySurface.size()-1; i>=0; i--) {
WindowState w = mDestroySurface.get(i);
- pw.println(" Destroy #" + i + ":");
+ pw.print(" Destroy #"); pw.print(i); pw.print(' ');
+ pw.print(w); pw.println(":");
w.dump(pw, " ");
}
}
@@ -8699,7 +8869,8 @@
pw.println(" Windows losing focus:");
for (int i=mLosingFocus.size()-1; i>=0; i--) {
WindowState w = mLosingFocus.get(i);
- pw.println(" Losing #" + i + ":");
+ pw.print(" Losing #"); pw.print(i); pw.print(' ');
+ pw.print(w); pw.println(":");
w.dump(pw, " ");
}
}
@@ -8709,7 +8880,7 @@
Iterator<Session> it = mSessions.iterator();
while (it.hasNext()) {
Session s = it.next();
- pw.println(" Session " + s);
+ pw.print(" Session "); pw.print(s); pw.println(':');
s.dump(pw, " ");
}
}
@@ -8719,7 +8890,7 @@
Iterator<WindowToken> it = mTokenMap.values().iterator();
while (it.hasNext()) {
WindowToken token = it.next();
- pw.println(" Token " + token.token);
+ pw.print(" Token "); pw.print(token.token); pw.println(':');
token.dump(pw, " ");
}
}
@@ -8727,14 +8898,16 @@
pw.println(" ");
pw.println(" Window token list:");
for (int i=0; i<mTokenList.size(); i++) {
- pw.println(" WindowToken #" + i + ": " + mTokenList.get(i));
+ pw.print(" #"); pw.print(i); pw.print(": ");
+ pw.println(mTokenList.get(i));
}
}
if (mAppTokens.size() > 0) {
pw.println(" ");
pw.println(" Application tokens in Z order:");
for (int i=mAppTokens.size()-1; i>=0; i--) {
- pw.println(" AppWindowToken #" + i + ": " + mAppTokens.get(i));
+ pw.print(" App #"); pw.print(i); pw.print(": ");
+ pw.println(mAppTokens.get(i));
}
}
if (mFinishedStarting.size() > 0) {
@@ -8742,7 +8915,8 @@
pw.println(" Finishing start of application tokens:");
for (int i=mFinishedStarting.size()-1; i>=0; i--) {
WindowToken token = mFinishedStarting.get(i);
- pw.println(" Finish Starting App Token #" + i + ":");
+ pw.print(" Finished Starting #"); pw.print(i);
+ pw.print(' '); pw.print(token); pw.println(':');
token.dump(pw, " ");
}
}
@@ -8751,7 +8925,8 @@
pw.println(" Exiting tokens:");
for (int i=mExitingTokens.size()-1; i>=0; i--) {
WindowToken token = mExitingTokens.get(i);
- pw.println(" Exiting Token #" + i + ":");
+ pw.print(" Exiting #"); pw.print(i);
+ pw.print(' '); pw.print(token); pw.println(':');
token.dump(pw, " ");
}
}
@@ -8760,54 +8935,59 @@
pw.println(" Exiting application tokens:");
for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
WindowToken token = mExitingAppTokens.get(i);
- pw.println(" Exiting App Token #" + i + ":");
+ pw.print(" Exiting App #"); pw.print(i);
+ pw.print(' '); pw.print(token); pw.println(':');
token.dump(pw, " ");
}
}
pw.println(" ");
- pw.println(" mCurrentFocus=" + mCurrentFocus);
- pw.println(" mLastFocus=" + mLastFocus);
- pw.println(" mFocusedApp=" + mFocusedApp);
- pw.println(" mInputMethodTarget=" + mInputMethodTarget);
- pw.println(" mInputMethodWindow=" + mInputMethodWindow);
- pw.println(" mInTouchMode=" + mInTouchMode);
- pw.println(" mSystemBooted=" + mSystemBooted
- + " mDisplayEnabled=" + mDisplayEnabled);
- pw.println(" mLayoutNeeded=" + mLayoutNeeded
- + " mBlurShown=" + mBlurShown);
- pw.println(" mDimShown=" + mDimShown
- + " current=" + mDimCurrentAlpha
- + " target=" + mDimTargetAlpha
- + " delta=" + mDimDeltaPerMs
- + " lastAnimTime=" + mLastDimAnimTime);
- pw.println(" mInputMethodAnimLayerAdjustment="
- + mInputMethodAnimLayerAdjustment);
- pw.println(" mDisplayFrozen=" + mDisplayFrozen
- + " mWindowsFreezingScreen=" + mWindowsFreezingScreen
- + " mAppsFreezingScreen=" + mAppsFreezingScreen);
- pw.println(" mRotation=" + mRotation
- + ", mForcedAppOrientation=" + mForcedAppOrientation
- + ", mRequestedRotation=" + mRequestedRotation);
- pw.println(" mAnimationPending=" + mAnimationPending
- + " mWindowAnimationScale=" + mWindowAnimationScale
- + " mTransitionWindowAnimationScale=" + mTransitionAnimationScale);
- pw.println(" mNextAppTransition=0x"
- + Integer.toHexString(mNextAppTransition)
- + ", mAppTransitionReady=" + mAppTransitionReady
- + ", mAppTransitionTimeout=" + mAppTransitionTimeout);
- pw.println(" mStartingIconInTransition=" + mStartingIconInTransition
- + ", mSkipAppTransitionAnimation=" + mSkipAppTransitionAnimation);
- pw.println(" mOpeningApps=" + mOpeningApps);
- pw.println(" mClosingApps=" + mClosingApps);
- pw.println(" DisplayWidth=" + mDisplay.getWidth()
- + " DisplayHeight=" + mDisplay.getHeight());
+ pw.print(" mCurrentFocus="); pw.println(mCurrentFocus);
+ pw.print(" mLastFocus="); pw.println(mLastFocus);
+ pw.print(" mFocusedApp="); pw.println(mFocusedApp);
+ pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget);
+ pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow);
+ pw.print(" mInTouchMode="); pw.println(mInTouchMode);
+ pw.print(" mSystemBooted="); pw.print(mSystemBooted);
+ pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
+ pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded);
+ pw.print(" mBlurShown="); pw.println(mBlurShown);
+ pw.print(" mDimShown="); pw.print(mDimShown);
+ pw.print(" current="); pw.print(mDimCurrentAlpha);
+ pw.print(" target="); pw.print(mDimTargetAlpha);
+ pw.print(" delta="); pw.print(mDimDeltaPerMs);
+ pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
+ pw.print(" mInputMethodAnimLayerAdjustment=");
+ pw.println(mInputMethodAnimLayerAdjustment);
+ pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen);
+ pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen);
+ pw.print(" mAppsFreezingScreen="); pw.println(mAppsFreezingScreen);
+ pw.print(" mRotation="); pw.print(mRotation);
+ pw.print(", mForcedAppOrientation="); pw.print(mForcedAppOrientation);
+ pw.print(", mRequestedRotation="); pw.println(mRequestedRotation);
+ pw.print(" mAnimationPending="); pw.print(mAnimationPending);
+ pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale);
+ pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale);
+ pw.print(" mNextAppTransition=0x");
+ pw.print(Integer.toHexString(mNextAppTransition));
+ pw.print(", mAppTransitionReady="); pw.print(mAppTransitionReady);
+ pw.print(", mAppTransitionTimeout="); pw.println( mAppTransitionTimeout);
+ pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition);
+ pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
+ if (mOpeningApps.size() > 0) {
+ pw.print(" mOpeningApps="); pw.println(mOpeningApps);
+ }
+ if (mClosingApps.size() > 0) {
+ pw.print(" mClosingApps="); pw.println(mClosingApps);
+ }
+ pw.print(" DisplayWidth="); pw.print(mDisplay.getWidth());
+ pw.print(" DisplayHeight="); pw.println(mDisplay.getHeight());
pw.println(" KeyWaiter state:");
- pw.println(" mLastWin=" + mKeyWaiter.mLastWin
- + " mLastBinder=" + mKeyWaiter.mLastBinder);
- pw.println(" mFinished=" + mKeyWaiter.mFinished
- + " mGotFirstWindow=" + mKeyWaiter.mGotFirstWindow
- + " mEventDispatching=" + mKeyWaiter.mEventDispatching
- + " mTimeToSwitch=" + mKeyWaiter.mTimeToSwitch);
+ pw.print(" mLastWin="); pw.print(mKeyWaiter.mLastWin);
+ pw.print(" mLastBinder="); pw.println(mKeyWaiter.mLastBinder);
+ pw.print(" mFinished="); pw.print(mKeyWaiter.mFinished);
+ pw.print(" mGotFirstWindow="); pw.print(mKeyWaiter.mGotFirstWindow);
+ pw.print(" mEventDispatching="); pw.print(mKeyWaiter.mEventDispatching);
+ pw.print(" mTimeToSwitch="); pw.println(mKeyWaiter.mTimeToSwitch);
}
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index d676c00..9471eff 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -169,6 +169,10 @@
static final int LOG_BOOT_PROGRESS_AMS_READY = 3040;
static final int LOG_BOOT_PROGRESS_ENABLE_SCREEN = 3050;
+ // The flags that are set for all calls we make to the package manager.
+ static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES
+ | PackageManager.GET_SUPPORTS_DENSITIES;
+
private static final String SYSTEM_SECURE = "ro.secure";
// This is the maximum number of application processes we would like
@@ -682,6 +686,11 @@
HashMap<String, IBinder> mAppBindArgs;
/**
+ * Temporary to avoid allocations. Protected by main lock.
+ */
+ final StringBuilder mStringBuilder = new StringBuilder(256);
+
+ /**
* Used to control how we initialize the service.
*/
boolean mStartRunning = false;
@@ -702,6 +711,11 @@
boolean mSleeping = false;
/**
+ * Set if we are shutting down the system, similar to sleeping.
+ */
+ boolean mShuttingDown = false;
+
+ /**
* Set when the system is going to sleep, until we have
* successfully paused the current activity and released our wake lock.
* At that point the system is allowed to actually sleep.
@@ -778,6 +792,8 @@
long mLastCpuTime = 0;
long mLastWriteTime = 0;
+ long mInitialStartTime = 0;
+
/**
* Set to true after the system has finished booting.
*/
@@ -861,7 +877,7 @@
return;
}
AppErrorResult res = (AppErrorResult) data.get("result");
- if (!mSleeping) {
+ if (!mSleeping && !mShuttingDown) {
Dialog d = new AppErrorDialog(
mContext, res, proc,
(Integer)data.get("flags"),
@@ -1046,7 +1062,7 @@
ApplicationInfo info =
mSelf.mContext.getPackageManager().getApplicationInfo(
- "android", PackageManager.GET_SHARED_LIBRARY_FILES);
+ "android", STOCK_PM_FLAGS);
synchronized (mSelf) {
ProcessRecord app = mSelf.newProcessRecordLocked(
mSystemThread.getApplicationThread(), info,
@@ -1270,7 +1286,7 @@
mBatteryStatsService.getActiveStatistics().writeLocked();
mUsageStatsService = new UsageStatsService( new File(
- systemDir, "usagestats.bin").toString());
+ systemDir, "usagestats").toString());
mConfiguration.makeDefault();
mProcessStats.init();
@@ -1635,6 +1651,11 @@
if (r.startTime == 0) {
r.startTime = SystemClock.uptimeMillis();
+ if (mInitialStartTime == 0) {
+ mInitialStartTime = r.startTime;
+ }
+ } else if (mInitialStartTime == 0) {
+ mInitialStartTime = SystemClock.uptimeMillis();
}
if (app != null && app.thread != null) {
@@ -1785,7 +1806,8 @@
Watchdog.getInstance().processStarted(app, app.processName, pid);
}
- StringBuilder buf = new StringBuilder(128);
+ StringBuilder buf = mStringBuilder;
+ buf.setLength(0);
buf.append("Start proc ");
buf.append(app.processName);
buf.append(" for ");
@@ -1880,7 +1902,7 @@
// If we are not going to sleep, we want to ensure the device is
// awake until the next activity is started.
- if (!mSleeping) {
+ if (!mSleeping && !mShuttingDown) {
mLaunchingActivity.acquire();
if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
// To be safe, don't allow the wake lock to be held for too long.
@@ -1959,12 +1981,15 @@
mPausingActivity = null;
}
- if (!mSleeping) {
+ if (!mSleeping && !mShuttingDown) {
resumeTopActivityLocked(prev);
} else {
if (mGoingToSleep.isHeld()) {
mGoingToSleep.release();
}
+ if (mShuttingDown) {
+ notifyAll();
+ }
}
if (prev != null) {
@@ -2203,7 +2228,7 @@
}
ActivityInfo aInfo =
intent.resolveActivityInfo(mContext.getPackageManager(),
- PackageManager.GET_SHARED_LIBRARY_FILES);
+ STOCK_PM_FLAGS);
if (aInfo != null) {
intent.setComponent(new ComponentName(
aInfo.applicationInfo.packageName, aInfo.name));
@@ -2230,7 +2255,8 @@
// If we are sleeping, and there is no resumed activity, and the top
// activity is paused, well that is the state we want.
- if (mSleeping && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
+ if ((mSleeping || mShuttingDown)
+ && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
mWindowManager.executeAppTransition();
@@ -2813,7 +2839,6 @@
HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
intent, resolvedType, aInfo, mConfiguration,
resultRecord, resultWho, requestCode, componentSpecified);
- r.startTime = SystemClock.uptimeMillis();
HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
!= 0 ? r : null;
@@ -3160,7 +3185,7 @@
ActivityThread.getPackageManager().resolveIntent(
intent, resolvedType,
PackageManager.MATCH_DEFAULT_ONLY
- | PackageManager.GET_SHARED_LIBRARY_FILES);
+ | STOCK_PM_FLAGS);
aInfo = rInfo != null ? rInfo.activityInfo : null;
} catch (RemoteException e) {
aInfo = null;
@@ -3221,8 +3246,7 @@
List<ResolveInfo> resolves =
ActivityThread.getPackageManager().queryIntentActivities(
intent, r.resolvedType,
- PackageManager.MATCH_DEFAULT_ONLY
- | PackageManager.GET_SHARED_LIBRARY_FILES);
+ PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
// Look for the original activity in the list...
final int N = resolves != null ? resolves.size() : 0;
@@ -3304,8 +3328,7 @@
ResolveInfo rInfo =
ActivityThread.getPackageManager().resolveIntent(
intent, resolvedType,
- PackageManager.MATCH_DEFAULT_ONLY
- | PackageManager.GET_SHARED_LIBRARY_FILES);
+ PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
aInfo = rInfo != null ? rInfo.activityInfo : null;
} catch (RemoteException e) {
aInfo = null;
@@ -4095,7 +4118,8 @@
}
}
- StringBuilder info = new StringBuilder();
+ StringBuilder info = mStringBuilder;
+ info.setLength(0);
info.append("ANR (application not responding) in process: ");
info.append(app.processName);
if (annotation != null) {
@@ -4517,7 +4541,7 @@
}
} else if (mStartingProcesses.size() > 0) {
app = mStartingProcesses.remove(0);
- app.pid = pid;
+ app.setPid(pid);
} else {
app = null;
}
@@ -4586,7 +4610,8 @@
mWaitForDebugger = mOrigWaitForDebugger;
}
}
- thread.bindApplication(processName, app.info, providers,
+ thread.bindApplication(processName, app.instrumentationInfo != null
+ ? app.instrumentationInfo : app.info, providers,
app.instrumentationClass, app.instrumentationProfileFile,
app.instrumentationArguments, app.instrumentationWatcher, testMode,
mConfiguration, getCommonServicesLocked());
@@ -6629,8 +6654,7 @@
try {
providers = ActivityThread.getPackageManager().
queryContentProviders(app.processName, app.info.uid,
- PackageManager.GET_SHARED_LIBRARY_FILES
- | PackageManager.GET_URI_PERMISSION_PATTERNS);
+ STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
} catch (RemoteException ex) {
}
if (providers != null) {
@@ -6734,7 +6758,8 @@
} else {
try {
cpi = ActivityThread.getPackageManager().
- resolveContentProvider(name, PackageManager.GET_URI_PERMISSION_PATTERNS);
+ resolveContentProvider(name,
+ STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
} catch (RemoteException ex) {
}
if (cpi == null) {
@@ -6755,7 +6780,7 @@
ActivityThread.getPackageManager().
getApplicationInfo(
cpi.applicationInfo.packageName,
- PackageManager.GET_SHARED_LIBRARY_FILES);
+ STOCK_PM_FLAGS);
if (ai == null) {
Log.w(TAG, "No package info for content provider "
+ cpi.name);
@@ -7085,8 +7110,45 @@
}
}
+ public boolean shutdown(int timeout) {
+ if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires permission "
+ + android.Manifest.permission.SHUTDOWN);
+ }
+
+ boolean timedout = false;
+
+ synchronized(this) {
+ mShuttingDown = true;
+ mWindowManager.setEventDispatching(false);
+
+ if (mResumedActivity != null) {
+ pauseIfSleepingLocked();
+ final long endTime = System.currentTimeMillis() + timeout;
+ while (mResumedActivity != null || mPausingActivity != null) {
+ long delay = endTime - System.currentTimeMillis();
+ if (delay <= 0) {
+ Log.w(TAG, "Activity manager shutdown timed out");
+ timedout = true;
+ break;
+ }
+ try {
+ this.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ }
+
+ mUsageStatsService.shutdown();
+ mBatteryStatsService.shutdown();
+
+ return timedout;
+ }
+
void pauseIfSleepingLocked() {
- if (mSleeping) {
+ if (mSleeping || mShuttingDown) {
if (!mGoingToSleep.isHeld()) {
mGoingToSleep.acquire();
if (mLaunchingActivity.isHeld()) {
@@ -7454,7 +7516,7 @@
if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
ResolveInfo ri = mContext.getPackageManager()
.resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
- 0);
+ STOCK_PM_FLAGS);
CharSequence errorMsg = null;
if (ri != null) {
ActivityInfo ai = ri.activityInfo;
@@ -7490,7 +7552,7 @@
if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
try {
List apps = ActivityThread.getPackageManager().
- getPersistentApplications(PackageManager.GET_SHARED_LIBRARY_FILES);
+ getPersistentApplications(STOCK_PM_FLAGS);
if (apps != null) {
int N = apps.size();
int i;
@@ -7877,24 +7939,24 @@
return;
}
pw.println("Activities in Current Activity Manager State:");
- dumpHistoryList(pw, mHistory, " ", "History");
+ dumpHistoryList(pw, mHistory, " ", "Hist", true);
pw.println(" ");
pw.println(" Running activities (most recent first):");
- dumpHistoryList(pw, mLRUActivities, " ", "Running");
+ dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
if (mWaitingVisibleActivities.size() > 0) {
pw.println(" ");
pw.println(" Activities waiting for another to become visible:");
- dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Waiting");
+ dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
}
if (mStoppingActivities.size() > 0) {
pw.println(" ");
pw.println(" Activities waiting to stop:");
- dumpHistoryList(pw, mStoppingActivities, " ", "Stopping");
+ dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
}
if (mFinishingActivities.size() > 0) {
pw.println(" ");
pw.println(" Activities waiting to finish:");
- dumpHistoryList(pw, mFinishingActivities, " ", "Finishing");
+ dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
}
pw.println(" ");
@@ -7909,7 +7971,9 @@
final int N = mRecentTasks.size();
for (int i=0; i<N; i++) {
- pw.println(" Recent Task #" + i);
+ TaskRecord tr = mRecentTasks.get(i);
+ pw.print(" * Recent #"); pw.print(i); pw.print(": ");
+ pw.println(tr);
mRecentTasks.get(i).dump(pw, " ");
}
}
@@ -7931,8 +7995,9 @@
needSep = true;
}
ProcessRecord r = procs.valueAt(ia);
- pw.println((r.persistent ? " *PERSISTENT* Process [" : " Process [")
- + r.processName + "] UID " + procs.keyAt(ia));
+ pw.print(r.persistent ? " *PERS*" : " *APP*");
+ pw.print(" UID "); pw.print(procs.keyAt(ia));
+ pw.print(" "); pw.println(r);
r.dump(pw, " ");
if (r.persistent) {
numPers++;
@@ -7945,7 +8010,7 @@
needSep = true;
pw.println(" Running processes (most recent first):");
dumpProcessList(pw, mLRUProcesses, " ",
- "Running Norm Proc", "Running PERS Proc", true);
+ "App ", "PERS", true);
needSep = true;
}
@@ -7955,8 +8020,8 @@
needSep = true;
pw.println(" PID mappings:");
for (int i=0; i<mPidsSelfLocked.size(); i++) {
- pw.println(" PID #" + mPidsSelfLocked.keyAt(i)
- + ": " + mPidsSelfLocked.valueAt(i));
+ pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
+ pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
}
}
}
@@ -7966,8 +8031,8 @@
needSep = true;
pw.println(" Foreground Processes:");
for (int i=0; i<mForegroundProcesses.size(); i++) {
- pw.println(" PID #" + mForegroundProcesses.keyAt(i)
- + ": " + mForegroundProcesses.valueAt(i));
+ pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
+ pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
}
}
@@ -7976,7 +8041,7 @@
needSep = true;
pw.println(" Persisent processes that are starting:");
dumpProcessList(pw, mPersistentStartingProcesses, " ",
- "Starting Initial Proc", "Restarting PERS Proc", false);
+ "Starting Norm", "Restarting PERS", false);
}
if (mStartingProcesses.size() > 0) {
@@ -7984,7 +8049,7 @@
needSep = true;
pw.println(" Processes that are starting:");
dumpProcessList(pw, mStartingProcesses, " ",
- "Starting Norm Proc", "Starting PERS Proc", false);
+ "Starting Norm", "Starting PERS", false);
}
if (mRemovedProcesses.size() > 0) {
@@ -7992,7 +8057,7 @@
needSep = true;
pw.println(" Processes that are being removed:");
dumpProcessList(pw, mRemovedProcesses, " ",
- "Removed Norm Proc", "Removed PERS Proc", false);
+ "Removed Norm", "Removed PERS", false);
}
if (mProcessesOnHold.size() > 0) {
@@ -8000,7 +8065,7 @@
needSep = true;
pw.println(" Processes that are on old until the system is ready:");
dumpProcessList(pw, mProcessesOnHold, " ",
- "OnHold Norm Proc", "OnHold PERS Proc", false);
+ "OnHold Norm", "OnHold PERS", false);
}
if (mProcessCrashTimes.getMap().size() > 0) {
@@ -8013,10 +8078,11 @@
SparseArray<Long> uids = procs.getValue();
final int N = uids.size();
for (int i=0; i<N; i++) {
- pw.println(" Process " + procs.getKey()
- + " uid " + uids.keyAt(i)
- + ": last crashed "
- + (now-uids.valueAt(i)) + " ms ago");
+ pw.print(" Process "); pw.print(procs.getKey());
+ pw.print(" uid "); pw.print(uids.keyAt(i));
+ pw.print(": last crashed ");
+ pw.print((now-uids.valueAt(i)));
+ pw.println(" ms ago");
}
}
}
@@ -8030,9 +8096,10 @@
SparseArray<Long> uids = procs.getValue();
final int N = uids.size();
for (int i=0; i<N; i++) {
- pw.println(" Bad process " + procs.getKey()
- + " uid " + uids.keyAt(i)
- + ": crashed at time " + uids.valueAt(i));
+ pw.print(" Bad process "); pw.print(procs.getKey());
+ pw.print(" uid "); pw.print(uids.keyAt(i));
+ pw.print(": crashed at time ");
+ pw.println(uids.valueAt(i));
}
}
}
@@ -8046,7 +8113,7 @@
+ " mBooting=" + mBooting
+ " mBooted=" + mBooted
+ " mFactoryTest=" + mFactoryTest);
- pw.println(" mSleeping=" + mSleeping);
+ pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
pw.println(" mGoingToSleep=" + mGoingToSleep);
pw.println(" mLaunchingActivity=" + mLaunchingActivity);
pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
@@ -8131,14 +8198,14 @@
Iterator it = mRegisteredReceivers.values().iterator();
while (it.hasNext()) {
ReceiverList r = (ReceiverList)it.next();
- pw.println(" Receiver " + r.receiver);
+ pw.print(" * "); pw.println(r);
r.dump(pw, " ");
}
}
pw.println(" ");
pw.println("Receiver Resolver Table:");
- mReceiverResolver.dump(new PrintWriterPrinter(pw), " ");
+ mReceiverResolver.dump(pw, " ");
if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
|| mPendingBroadcast != null) {
@@ -8172,13 +8239,23 @@
if (mStickyBroadcasts != null) {
pw.println(" ");
pw.println(" Sticky broadcasts:");
+ StringBuilder sb = new StringBuilder(128);
for (Map.Entry<String, ArrayList<Intent>> ent
: mStickyBroadcasts.entrySet()) {
- pw.println(" Sticky action " + ent.getKey() + ":");
+ pw.print(" * Sticky action "); pw.print(ent.getKey());
+ pw.println(":");
ArrayList<Intent> intents = ent.getValue();
final int N = intents.size();
for (int i=0; i<N; i++) {
- pw.println(" " + intents.get(i));
+ sb.setLength(0);
+ sb.append(" Intent: ");
+ intents.get(i).toShortString(sb, true, false);
+ pw.println(sb.toString());
+ Bundle bundle = intents.get(i).getExtras();
+ if (bundle != null) {
+ pw.print(" ");
+ pw.println(bundle.toString());
+ }
}
}
}
@@ -8209,7 +8286,7 @@
Iterator<ServiceRecord> it = mServices.values().iterator();
while (it.hasNext()) {
ServiceRecord r = it.next();
- pw.println(" Service " + r.shortName);
+ pw.print(" * "); pw.println(r);
r.dump(pw, " ");
}
needSep = true;
@@ -8220,7 +8297,7 @@
pw.println(" Pending services:");
for (int i=0; i<mPendingServices.size(); i++) {
ServiceRecord r = mPendingServices.get(i);
- pw.println(" Pending Service " + r.shortName);
+ pw.print(" * Pending "); pw.println(r);
r.dump(pw, " ");
}
needSep = true;
@@ -8231,7 +8308,7 @@
pw.println(" Restarting services:");
for (int i=0; i<mRestartingServices.size(); i++) {
ServiceRecord r = mRestartingServices.get(i);
- pw.println(" Restarting Service " + r.shortName);
+ pw.print(" * Restarting "); pw.println(r);
r.dump(pw, " ");
}
needSep = true;
@@ -8242,7 +8319,7 @@
pw.println(" Stopping services:");
for (int i=0; i<mStoppingServices.size(); i++) {
ServiceRecord r = mStoppingServices.get(i);
- pw.println(" Stopping Service " + r.shortName);
+ pw.print(" * Stopping "); pw.println(r);
r.dump(pw, " ");
}
needSep = true;
@@ -8255,8 +8332,7 @@
= mServiceConnections.values().iterator();
while (it.hasNext()) {
ConnectionRecord r = it.next();
- pw.println(" " + r.binding.service.shortName
- + " -> " + r.conn.asBinder());
+ pw.print(" * "); pw.println(r);
r.dump(pw, " ");
}
}
@@ -8279,18 +8355,6 @@
boolean needSep = false;
- if (mProvidersByName.size() > 0) {
- pw.println(" Published content providers (by name):");
- Iterator it = mProvidersByName.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry e = (Map.Entry)it.next();
- ContentProviderRecord r = (ContentProviderRecord)e.getValue();
- pw.println(" Provider " + (String)e.getKey());
- r.dump(pw, " ");
- }
- needSep = true;
- }
-
if (mProvidersByClass.size() > 0) {
if (needSep) pw.println(" ");
pw.println(" Published content providers (by class):");
@@ -8298,31 +8362,48 @@
while (it.hasNext()) {
Map.Entry e = (Map.Entry)it.next();
ContentProviderRecord r = (ContentProviderRecord)e.getValue();
- pw.println(" Provider " + (String)e.getKey());
+ pw.print(" * "); pw.println(r);
r.dump(pw, " ");
}
needSep = true;
}
+ if (mProvidersByName.size() > 0) {
+ pw.println(" ");
+ pw.println(" Authority to provider mappings:");
+ Iterator it = mProvidersByName.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry e = (Map.Entry)it.next();
+ ContentProviderRecord r = (ContentProviderRecord)e.getValue();
+ pw.print(" "); pw.print(e.getKey()); pw.print(": ");
+ pw.println(r);
+ }
+ needSep = true;
+ }
+
if (mLaunchingProviders.size() > 0) {
if (needSep) pw.println(" ");
pw.println(" Launching content providers:");
for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
- pw.println(" Provider #" + i + ":");
- ((ContentProviderRecord)mLaunchingProviders.get(i)).dump(pw, " ");
+ pw.print(" Launching #"); pw.print(i); pw.print(": ");
+ pw.println(mLaunchingProviders.get(i));
}
needSep = true;
}
- pw.println();
- pw.println("Granted Uri Permissions:");
- for (int i=0; i<mGrantedUriPermissions.size(); i++) {
- int uid = mGrantedUriPermissions.keyAt(i);
- HashMap<Uri, UriPermission> perms
- = mGrantedUriPermissions.valueAt(i);
- pw.println(" Uris granted to uid " + uid + ":");
- for (UriPermission perm : perms.values()) {
- perm.dump(pw, " ");
+ if (mGrantedUriPermissions.size() > 0) {
+ pw.println();
+ pw.println("Granted Uri Permissions:");
+ for (int i=0; i<mGrantedUriPermissions.size(); i++) {
+ int uid = mGrantedUriPermissions.keyAt(i);
+ HashMap<Uri, UriPermission> perms
+ = mGrantedUriPermissions.valueAt(i);
+ pw.print(" * UID "); pw.print(uid);
+ pw.println(" holds:");
+ for (UriPermission perm : perms.values()) {
+ pw.print(" "); pw.println(perm);
+ perm.dump(pw, " ");
+ }
}
}
}
@@ -8340,7 +8421,7 @@
return;
}
- pw.println("Intent Senders in Current Activity Manager State:");
+ pw.println("Pending Intents in Current Activity Manager State:");
if (this.mIntentSenderRecords.size() > 0) {
Iterator<WeakReference<PendingIntentRecord>> it
@@ -8349,10 +8430,10 @@
WeakReference<PendingIntentRecord> ref = it.next();
PendingIntentRecord rec = ref != null ? ref.get(): null;
if (rec != null) {
- pw.println(" IntentSender " + rec);
+ pw.print(" * "); pw.println(rec);
rec.dump(pw, " ");
} else {
- pw.println(" IntentSender " + ref);
+ pw.print(" * "); pw.print(ref);
}
}
}
@@ -8360,16 +8441,26 @@
}
private static final void dumpHistoryList(PrintWriter pw, List list,
- String prefix, String label) {
+ String prefix, String label, boolean complete) {
TaskRecord lastTask = null;
for (int i=list.size()-1; i>=0; i--) {
HistoryRecord r = (HistoryRecord)list.get(i);
+ final boolean full = complete || !r.inHistory;
if (lastTask != r.task) {
lastTask = r.task;
- lastTask.dump(pw, prefix + " ");
+ pw.print(prefix);
+ pw.print(full ? "* " : " ");
+ pw.println(lastTask);
+ if (full) {
+ lastTask.dump(pw, prefix + " ");
+ }
}
- pw.println(prefix + " " + label + " #" + i + ":");
- r.dump(pw, prefix + " ");
+ pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
+ pw.print(" #"); pw.print(i); pw.print(": ");
+ pw.println(r);
+ if (full) {
+ r.dump(pw, prefix + " ");
+ }
}
}
@@ -8401,7 +8492,7 @@
private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
PrintWriter pw, List list, String prefix, String[] args) {
- final boolean isCheckinRequest = scanArgs(args, "-c");
+ final boolean isCheckinRequest = scanArgs(args, "--checkin");
long uptime = SystemClock.uptimeMillis();
long realtime = SystemClock.elapsedRealtime();
@@ -8738,7 +8829,7 @@
mPidsSelfLocked.remove(app.pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
- app.pid = 0;
+ app.setPid(0);
}
}
@@ -8876,7 +8967,7 @@
try {
ResolveInfo rInfo =
ActivityThread.getPackageManager().resolveService(
- service, resolvedType, PackageManager.GET_SHARED_LIBRARY_FILES);
+ service, resolvedType, STOCK_PM_FLAGS);
ServiceInfo sInfo =
rInfo != null ? rInfo.serviceInfo : null;
if (sInfo == null) {
@@ -10094,7 +10185,7 @@
if (intent.getComponent() != null) {
// Broadcast is going to one specific receiver class...
ActivityInfo ai = ActivityThread.getPackageManager().
- getReceiverInfo(intent.getComponent(), 0);
+ getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
if (ai != null) {
receivers = new ArrayList();
ResolveInfo ri = new ResolveInfo();
@@ -10107,7 +10198,7 @@
== 0) {
receivers =
ActivityThread.getPackageManager().queryIntentReceivers(
- intent, resolvedType, PackageManager.GET_SHARED_LIBRARY_FILES);
+ intent, resolvedType, STOCK_PM_FLAGS);
}
registeredReceivers = mReceiverResolver.queryIntent(resolver,
intent, resolvedType, false);
@@ -10844,9 +10935,9 @@
ApplicationInfo ai = null;
try {
ii = mContext.getPackageManager().getInstrumentationInfo(
- className, 0);
+ className, STOCK_PM_FLAGS);
ai = mContext.getPackageManager().getApplicationInfo(
- ii.targetPackage, PackageManager.GET_SHARED_LIBRARY_FILES);
+ ii.targetPackage, STOCK_PM_FLAGS);
} catch (PackageManager.NameNotFoundException e) {
}
if (ii == null) {
@@ -10878,6 +10969,7 @@
uninstallPackageLocked(ii.targetPackage, -1, true);
ProcessRecord app = addAppLocked(ai);
app.instrumentationClass = className;
+ app.instrumentationInfo = ai;
app.instrumentationProfileFile = profileFile;
app.instrumentationArguments = arguments;
app.instrumentationWatcher = watcher;
@@ -10925,6 +11017,7 @@
}
app.instrumentationWatcher = null;
app.instrumentationClass = null;
+ app.instrumentationInfo = null;
app.instrumentationProfileFile = null;
app.instrumentationArguments = null;
diff --git a/services/java/com/android/server/am/AppBindRecord.java b/services/java/com/android/server/am/AppBindRecord.java
index ce6f6dc..9c57360 100644
--- a/services/java/com/android/server/am/AppBindRecord.java
+++ b/services/java/com/android/server/am/AppBindRecord.java
@@ -32,9 +32,12 @@
// All ConnectionRecord for this client.
void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + this);
pw.println(prefix + "service=" + service);
pw.println(prefix + "client=" + client);
+ dumpInIntentBind(pw, prefix);
+ }
+
+ void dumpInIntentBind(PrintWriter pw, String prefix) {
if (connections.size() > 0) {
pw.println(prefix + "Per-process Connections:");
Iterator<ConnectionRecord> it = connections.iterator();
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index 9ad994c..0387be5 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -25,8 +25,7 @@
import android.os.Parcel;
import android.os.Process;
import android.os.ServiceManager;
-import android.telephony.TelephonyManager;
-import android.util.PrintWriterPrinter;
+import android.util.Log;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -50,6 +49,13 @@
ServiceManager.addService("batteryinfo", asBinder());
}
+ public void shutdown() {
+ Log.w("BatteryStats", "Writing battery stats before shutdown...");
+ synchronized (mStats) {
+ mStats.writeLocked();
+ }
+ }
+
public static IBatteryStats getService() {
if (sService != null) {
return sService;
@@ -255,6 +261,20 @@
}
}
+ public void noteWifiMulticastEnabled(int uid) {
+ enforceCallingPermission();
+ synchronized (mStats) {
+ mStats.noteWifiMulticastEnabledLocked(uid);
+ }
+ }
+
+ public void noteWifiMulticastDisabled(int uid) {
+ enforceCallingPermission();
+ synchronized (mStats) {
+ mStats.noteWifiMulticastDisabledLocked(uid);
+ }
+ }
+
public boolean isOnBattery() {
return mStats.isOnBattery();
}
@@ -264,6 +284,11 @@
mStats.setOnBattery(onBattery, level);
}
+ public void recordCurrentLevel(int level) {
+ enforceCallingPermission();
+ mStats.recordCurrentLevel(level);
+ }
+
public long getAwakeTimeBattery() {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BATTERY_STATS, null);
@@ -290,14 +315,14 @@
boolean isCheckin = false;
if (args != null) {
for (String arg : args) {
- if ("-c".equals(arg)) {
+ if ("--checkin".equals(arg)) {
isCheckin = true;
break;
}
}
}
if (isCheckin) mStats.dumpCheckinLocked(pw, args);
- else mStats.dumpLocked(new PrintWriterPrinter(pw));
+ else mStats.dumpLocked(pw);
}
}
}
diff --git a/services/java/com/android/server/am/BroadcastFilter.java b/services/java/com/android/server/am/BroadcastFilter.java
index cd7f720..0eeb393 100644
--- a/services/java/com/android/server/am/BroadcastFilter.java
+++ b/services/java/com/android/server/am/BroadcastFilter.java
@@ -18,6 +18,7 @@
import android.content.IntentFilter;
import android.util.PrintWriterPrinter;
+import android.util.Printer;
import java.io.PrintWriter;
@@ -33,19 +34,25 @@
requiredPermission = _requiredPermission;
}
- public void dumpLocal(PrintWriter pw, String prefix) {
- super.dump(new PrintWriterPrinter(pw), prefix);
- }
-
public void dump(PrintWriter pw, String prefix) {
- dumpLocal(pw, prefix);
- pw.println(prefix + "requiredPermission=" + requiredPermission);
+ dumpInReceiverList(pw, new PrintWriterPrinter(pw), prefix);
receiverList.dumpLocal(pw, prefix);
}
+ public void dumpInReceiverList(PrintWriter pw, Printer pr, String prefix) {
+ super.dump(pr, prefix);
+ if (requiredPermission != null) {
+ pw.print(prefix); pw.print("requiredPermission="); pw.println(requiredPermission);
+ }
+ }
+
public String toString() {
- return "BroadcastFilter{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + receiverList + "}";
+ StringBuilder sb = new StringBuilder();
+ sb.append("BroadcastFilter{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(' ');
+ sb.append(receiverList);
+ sb.append('}');
+ return sb.toString();
}
}
diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/java/com/android/server/am/ConnectionRecord.java
index 41a783f..b3343dd 100644
--- a/services/java/com/android/server/am/ConnectionRecord.java
+++ b/services/java/com/android/server/am/ConnectionRecord.java
@@ -28,11 +28,13 @@
final HistoryRecord activity; // If non-null, the owning activity.
final IServiceConnection conn; // The client connection.
final int flags; // Binding options.
-
+ String stringName; // Caching of toString.
+
void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + this);
pw.println(prefix + "binding=" + binding);
- pw.println(prefix + "activity=" + activity);
+ if (activity != null) {
+ pw.println(prefix + "activity=" + activity);
+ }
pw.println(prefix + "conn=" + conn.asBinder()
+ " flags=0x" + Integer.toHexString(flags));
}
@@ -46,9 +48,17 @@
}
public String toString() {
- return "ConnectionRecord{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + binding.service.shortName
- + ":@" + Integer.toHexString(System.identityHashCode(conn.asBinder())) + "}";
+ if (stringName != null) {
+ return stringName;
+ }
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("ConnectionRecord{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(' ');
+ sb.append(binding.service.shortName);
+ sb.append(":@");
+ sb.append(Integer.toHexString(System.identityHashCode(conn.asBinder())));
+ sb.append('}');
+ return stringName = sb.toString();
}
}
diff --git a/services/java/com/android/server/am/ContentProviderRecord.java b/services/java/com/android/server/am/ContentProviderRecord.java
index 9f37c14..c764635 100644
--- a/services/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/java/com/android/server/am/ContentProviderRecord.java
@@ -32,7 +32,8 @@
int externals; // number of non-framework processes supported by this provider
ProcessRecord app; // if non-null, hosting application
ProcessRecord launchingApp; // if non-null, waiting for this app to be launched.
-
+ String stringName;
+
public ContentProviderRecord(ProviderInfo _info, ApplicationInfo ai) {
super(_info);
uid = ai.uid;
@@ -53,24 +54,39 @@
}
void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + this);
- pw.println(prefix + "package=" + info.applicationInfo.packageName
- + " process=" + info.processName);
- pw.println(prefix + "app=" + app);
- pw.println(prefix + "launchingApp=" + launchingApp);
- pw.println(prefix + "provider=" + provider);
- pw.println(prefix + "name=" + info.authority);
- pw.println(prefix + "isSyncable=" + info.isSyncable);
- pw.println(prefix + "multiprocess=" + info.multiprocess
- + " initOrder=" + info.initOrder
- + " uid=" + uid);
- pw.println(prefix + "clients=" + clients);
- pw.println(prefix + "externals=" + externals);
+ pw.print(prefix); pw.print("package=");
+ pw.print(info.applicationInfo.packageName);
+ pw.print("process="); pw.println(info.processName);
+ pw.print(prefix); pw.print("app="); pw.println(app);
+ if (launchingApp != null) {
+ pw.print(prefix); pw.print("launchingApp="); pw.println(launchingApp);
+ }
+ pw.print(prefix); pw.print("uid="); pw.print(uid);
+ pw.print(" provider="); pw.println(provider);
+ pw.print(prefix); pw.print("name="); pw.println(info.authority);
+ if (info.isSyncable || info.multiprocess || info.initOrder != 0) {
+ pw.print(prefix); pw.print("isSyncable="); pw.print(info.isSyncable);
+ pw.print("multiprocess="); pw.print(info.multiprocess);
+ pw.print(" initOrder="); pw.println(info.initOrder);
+ }
+ if (clients.size() > 0) {
+ pw.print(prefix); pw.print("clients="); pw.println(clients);
+ }
+ if (externals != 0) {
+ pw.print(prefix); pw.print("externals="); pw.println(externals);
+ }
}
public String toString() {
- return "ContentProviderRecord{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + info.name + "}";
+ if (stringName != null) {
+ return stringName;
+ }
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("ContentProviderRecord{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(' ');
+ sb.append(info.name);
+ sb.append('}');
+ return stringName = sb.toString();
}
}
diff --git a/services/java/com/android/server/am/HistoryRecord.java b/services/java/com/android/server/am/HistoryRecord.java
index 0f62471..1488791 100644
--- a/services/java/com/android/server/am/HistoryRecord.java
+++ b/services/java/com/android/server/am/HistoryRecord.java
@@ -100,46 +100,74 @@
boolean hasBeenLaunched;// has this activity ever been launched?
boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
+ String stringName; // for caching of toString().
+
void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + this);
- pw.println(prefix + "packageName=" + packageName
- + " processName=" + processName);
- pw.println(prefix + "launchedFromUid=" + launchedFromUid
- + " app=" + app);
- pw.println(prefix + intent);
- pw.println(prefix + "frontOfTask=" + frontOfTask + " task=" + task);
- pw.println(prefix + "taskAffinity=" + taskAffinity);
- pw.println(prefix + "realActivity=" + realActivity);
- pw.println(prefix + "dir=" + baseDir + " res=" + resDir + " data=" + dataDir);
- pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes)
- + " icon=0x" + Integer.toHexString(icon)
- + " theme=0x" + Integer.toHexString(theme));
- pw.println(prefix + "stateNotNeeded=" + stateNotNeeded
- + " componentSpecified=" + componentSpecified
- + " isHomeActivity=" + isHomeActivity);
- pw.println(prefix + "configuration=" + configuration);
- pw.println(prefix + "resultTo=" + resultTo
- + " resultWho=" + resultWho + " resultCode=" + requestCode);
- pw.println(prefix + "results=" + results);
- pw.println(prefix + "pendingResults=" + pendingResults);
- pw.println(prefix + "readUriPermissions=" + readUriPermissions);
- pw.println(prefix + "writeUriPermissions=" + writeUriPermissions);
- pw.println(prefix + "launchFailed=" + launchFailed
- + " haveState=" + haveState + " icicle=" + icicle);
- pw.println(prefix + "state=" + state
- + " stopped=" + stopped + " finishing=" + finishing);
- pw.println(prefix + "keysPaused=" + keysPaused
- + " inHistory=" + inHistory + " persistent=" + persistent
- + " launchMode=" + launchMode);
- pw.println(prefix + "fullscreen=" + fullscreen
- + " visible=" + visible
- + " frozenBeforeDestroy=" + frozenBeforeDestroy
- + " thumbnailNeeded=" + thumbnailNeeded + " idle=" + idle);
- pw.println(prefix + "waitingVisible=" + waitingVisible
- + " nowVisible=" + nowVisible);
- pw.println(prefix + "configDestroy=" + configDestroy
- + " configChangeFlags=" + Integer.toHexString(configChangeFlags));
- pw.println(prefix + "connections=" + connections);
+ pw.print(prefix); pw.print("packageName="); pw.print(packageName);
+ pw.print(" processName="); pw.println(processName);
+ pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
+ pw.print(" app="); pw.println(app);
+ pw.print(prefix); pw.println(intent);
+ pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask);
+ pw.print(" task="); pw.println(task);
+ pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
+ pw.print(prefix); pw.print("realActivity=");
+ pw.println(realActivity.flattenToShortString());
+ pw.print(prefix); pw.print("base="); pw.print(baseDir);
+ if (!resDir.equals(baseDir)) pw.print(" res="); pw.print(resDir);
+ pw.print(" data="); pw.println(dataDir);
+ pw.print(prefix); pw.print("labelRes=0x");
+ pw.print(Integer.toHexString(labelRes));
+ pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
+ pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
+ pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
+ pw.print(" componentSpecified="); pw.print(componentSpecified);
+ pw.print(" isHomeActivity="); pw.println(isHomeActivity);
+ pw.print(prefix); pw.print("configuration="); pw.println(configuration);
+ if (resultTo != null || resultWho != null) {
+ pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
+ pw.print(" resultWho="); pw.print(resultWho);
+ pw.print(" resultCode="); pw.println(requestCode);
+ }
+ if (results != null) {
+ pw.print(prefix); pw.print("results="); pw.println(results);
+ }
+ if (pendingResults != null) {
+ pw.print(prefix); pw.print("pendingResults="); pw.println(pendingResults);
+ }
+ if (readUriPermissions != null) {
+ pw.print(prefix); pw.print("readUriPermissions="); pw.println(readUriPermissions);
+ }
+ if (writeUriPermissions != null) {
+ pw.print(prefix); pw.print("writeUriPermissions="); pw.println(writeUriPermissions);
+ }
+ pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
+ pw.print(" haveState="); pw.print(haveState);
+ pw.print(" icicle="); pw.println(icicle);
+ pw.print(prefix); pw.print("state="); pw.print(state);
+ pw.print(" stopped="); pw.print(stopped);
+ pw.print(" finishing="); pw.println(finishing);
+ pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
+ pw.print(" inHistory="); pw.print(inHistory);
+ pw.print(" persistent="); pw.print(persistent);
+ pw.print(" launchMode="); pw.println(launchMode);
+ pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen);
+ pw.print(" visible="); pw.print(visible);
+ pw.print(" frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
+ pw.print(" thumbnailNeeded="); pw.print(thumbnailNeeded);
+ pw.print(" idle="); pw.println(idle);
+ if (waitingVisible || nowVisible) {
+ pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible);
+ pw.print(" nowVisible="); pw.println(nowVisible);
+ }
+ if (configDestroy || configChangeFlags != 0) {
+ pw.print(prefix); pw.print("configDestroy="); pw.print(configDestroy);
+ pw.print(" configChangeFlags=");
+ pw.println(Integer.toHexString(configChangeFlags));
+ }
+ if (connections != null) {
+ pw.print(prefix); pw.print("connections="); pw.println(connections);
+ }
}
HistoryRecord(ActivityManagerService _service, ProcessRecord _caller,
@@ -335,15 +363,31 @@
public void windowsVisible() {
synchronized(service) {
- if (ActivityManagerService.SHOW_ACTIVITY_START_TIME
- && startTime != 0) {
- long time = SystemClock.uptimeMillis() - startTime;
- EventLog.writeEvent(ActivityManagerService.LOG_ACTIVITY_LAUNCH_TIME,
- System.identityHashCode(this), shortComponentName, time);
- Log.i(ActivityManagerService.TAG, "Displayed activity "
- + shortComponentName
- + ": " + time + " ms");
+ if (startTime != 0) {
+ final long curTime = SystemClock.uptimeMillis();
+ final long thisTime = curTime - startTime;
+ final long totalTime = service.mInitialStartTime != 0
+ ? (curTime - service.mInitialStartTime) : thisTime;
+ if (ActivityManagerService.SHOW_ACTIVITY_START_TIME) {
+ EventLog.writeEvent(ActivityManagerService.LOG_ACTIVITY_LAUNCH_TIME,
+ System.identityHashCode(this), shortComponentName,
+ thisTime, totalTime);
+ StringBuilder sb = service.mStringBuilder;
+ sb.setLength(0);
+ sb.append("Displayed activity ");
+ sb.append(shortComponentName);
+ sb.append(": ");
+ sb.append(thisTime);
+ sb.append(" ms (total ");
+ sb.append(totalTime);
+ sb.append(" ms)");
+ Log.i(ActivityManagerService.TAG, sb.toString());
+ }
+ if (totalTime > 0) {
+ service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
+ }
startTime = 0;
+ service.mInitialStartTime = 0;
}
if (ActivityManagerService.DEBUG_SWITCH) Log.v(
ActivityManagerService.TAG, "windowsVisible(): " + this);
@@ -453,8 +497,15 @@
public String toString() {
- return "HistoryRecord{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + intent.getComponent().toShortString() + "}";
+ if (stringName != null) {
+ return stringName;
+ }
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("HistoryRecord{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(' ');
+ sb.append(intent.getComponent().flattenToShortString());
+ sb.append('}');
+ return stringName = sb.toString();
}
}
diff --git a/services/java/com/android/server/am/IntentBindRecord.java b/services/java/com/android/server/am/IntentBindRecord.java
index 24c3943..3a5ca66 100644
--- a/services/java/com/android/server/am/IntentBindRecord.java
+++ b/services/java/com/android/server/am/IntentBindRecord.java
@@ -45,22 +45,30 @@
/** Set when the service's onUnbind() has asked to be told about new clients. */
boolean doRebind;
+ String stringName; // caching of toString
+
void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + this);
- pw.println(prefix + "service=" + service);
- pw.println(prefix + "intent=" + intent.getIntent());
- pw.println(prefix + "binder=" + binder
- + " requested=" + requested
- + " received=" + received
- + " hasBound=" + hasBound
- + " doRebind=" + doRebind);
+ pw.print(prefix); pw.print("service="); pw.println(service);
+ dumpInService(pw, prefix);
+ }
+
+ void dumpInService(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.print("intent={");
+ pw.print(intent.getIntent().toShortString(true, false));
+ pw.println('}');
+ pw.print(prefix); pw.print("binder="); pw.println(binder);
+ pw.print(prefix); pw.print("requested="); pw.print(requested);
+ pw.print(" received="); pw.print(received);
+ pw.print(" hasBound="); pw.print(hasBound);
+ pw.print(" doRebind="); pw.println(doRebind);
if (apps.size() > 0) {
- pw.println(prefix + "Application Bindings:");
Iterator<AppBindRecord> it = apps.values().iterator();
while (it.hasNext()) {
AppBindRecord a = it.next();
- pw.println(prefix + "Client " + a.client);
- a.dump(pw, prefix + " ");
+ pw.print(prefix); pw.print("* Client AppBindRecord{");
+ pw.print(Integer.toHexString(System.identityHashCode(a)));
+ pw.print(' '); pw.print(a.client); pw.println('}');
+ a.dumpInIntentBind(pw, prefix + " ");
}
}
}
@@ -71,9 +79,19 @@
}
public String toString() {
- return "IntentBindRecord{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + service.name.toShortString()
- + ":" + intent + "}";
+ if (stringName != null) {
+ return stringName;
+ }
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("IntentBindRecord{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(' ');
+ sb.append(service.shortName);
+ sb.append(':');
+ if (intent != null) {
+ intent.getIntent().toShortString(sb, false, false);
+ }
+ sb.append('}');
+ return stringName = sb.toString();
}
}
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
index b18aaf7..4381392 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -36,6 +36,8 @@
boolean sent = false;
boolean canceled = false;
+ String stringName;
+
final static class Key {
final int type;
final String packageName;
@@ -142,7 +144,7 @@
public String toString() {
return "Key{" + typeName() + " pkg=" + packageName
- + " intent=" + requestIntent + " flags=0x"
+ + " intent=" + requestIntent.toShortString(true, false) + " flags=0x"
+ Integer.toHexString(flags) + "}";
}
@@ -260,19 +262,38 @@
}
void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + "packageName=" + key.packageName
- + " type=" + key.typeName()
- + " flags=0x" + Integer.toHexString(key.flags));
- pw.println(prefix + "activity=" + key.activity + " who=" + key.who);
- pw.println(prefix + "requestCode=" + key.requestCode
- + " requestResolvedType=" + key.requestResolvedType);
- pw.println(prefix + "requestIntent=" + key.requestIntent);
- pw.println(prefix + "sent=" + sent + " canceled=" + canceled);
+ pw.print(prefix); pw.print("uid="); pw.print(uid);
+ pw.print(" packageName="); pw.print(key.packageName);
+ pw.print(" type="); pw.print(key.typeName());
+ pw.print(" flags=0x"); pw.println(Integer.toHexString(key.flags));
+ if (key.activity != null || key.who != null) {
+ pw.print(prefix); pw.print("activity="); pw.print(key.activity);
+ pw.print(" who="); pw.println(key.who);
+ }
+ if (key.requestCode != 0 || key.requestResolvedType != null) {
+ pw.print(prefix); pw.print("requestCode="); pw.print(key.requestCode);
+ pw.print(" requestResolvedType="); pw.println(key.requestResolvedType);
+ }
+ pw.print(prefix); pw.print("requestIntent=");
+ pw.println(key.requestIntent.toShortString(true, true));
+ if (sent || canceled) {
+ pw.print(prefix); pw.print("sent="); pw.print(sent);
+ pw.print(" canceled="); pw.println(canceled);
+ }
}
public String toString() {
- return "IntentSenderRecord{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + key.packageName + " " + key.typeName() + "}";
+ if (stringName != null) {
+ return stringName;
+ }
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("PendingIntentRecord{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(' ');
+ sb.append(key.packageName);
+ sb.append(' ');
+ sb.append(key.typeName());
+ sb.append('}');
+ return stringName = sb.toString();
}
}
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index a1320df..68aebc3 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -28,6 +28,7 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.PrintWriterPrinter;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -62,6 +63,7 @@
IBinder forcingToForeground;// Token that is forcing this process to be foreground
int adjSeq; // Sequence id for identifying repeated trav
ComponentName instrumentationClass;// class installed to instrument app
+ ApplicationInfo instrumentationInfo; // the application being instrumented
String instrumentationProfileFile; // where to save profiling
IInstrumentationWatcher instrumentationWatcher; // who is waiting
Bundle instrumentationArguments;// as given to us
@@ -98,44 +100,86 @@
boolean waitedForDebugger; // has process show wait for debugger dialog?
Dialog waitDialog; // current wait for debugger dialog
+ String stringName; // caching of toString() result.
+
// These reports are generated & stored when an app gets into an error condition.
// They will be "null" when all is OK.
ActivityManager.ProcessErrorStateInfo crashingReport;
ActivityManager.ProcessErrorStateInfo notRespondingReport;
void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + this);
- pw.println(prefix + "class=" + info.className);
- pw.println(prefix+"manageSpaceActivityName="+info.manageSpaceActivityName);
- pw.println(prefix + "dir=" + info.sourceDir + " publicDir=" + info.publicSourceDir
- + " data=" + info.dataDir);
- pw.println(prefix + "packageList=" + pkgList);
- pw.println(prefix + "instrumentationClass=" + instrumentationClass
- + " instrumentationProfileFile=" + instrumentationProfileFile);
- pw.println(prefix + "instrumentationArguments=" + instrumentationArguments);
- pw.println(prefix + "thread=" + thread + " curReceiver=" + curReceiver);
- pw.println(prefix + "pid=" + pid + " starting=" + starting
- + " lastPss=" + lastPss);
- pw.println(prefix + "maxAdj=" + maxAdj + " hiddenAdj=" + hiddenAdj
- + " curRawAdj=" + curRawAdj + " setRawAdj=" + setRawAdj
- + " curAdj=" + curAdj + " setAdj=" + setAdj);
- pw.println(prefix + "isForeground=" + isForeground
- + " setIsForeground=" + setIsForeground
- + " foregroundServices=" + foregroundServices
- + " forcingToForeground=" + forcingToForeground);
- pw.println(prefix + "persistent=" + persistent + " removed=" + removed
- + " persistentActivities=" + persistentActivities);
- pw.println(prefix + "debugging=" + debugging
- + " crashing=" + crashing + " " + crashDialog
- + " notResponding=" + notResponding + " " + anrDialog
- + " bad=" + bad);
- pw.println(prefix + "activities=" + activities);
- pw.println(prefix + "services=" + services);
- pw.println(prefix + "executingServices=" + executingServices);
- pw.println(prefix + "connections=" + connections);
- pw.println(prefix + "pubProviders=" + pubProviders);
- pw.println(prefix + "conProviders=" + conProviders);
- pw.println(prefix + "receivers=" + receivers);
+ if (info.className != null) {
+ pw.print(prefix); pw.print("class="); pw.println(info.className);
+ }
+ if (info.manageSpaceActivityName != null) {
+ pw.print(prefix); pw.print("manageSpaceActivityName=");
+ pw.println(info.manageSpaceActivityName);
+ }
+ pw.print(prefix); pw.print("dir="); pw.print(info.sourceDir);
+ pw.print(" publicDir="); pw.print(info.publicSourceDir);
+ pw.print(" data="); pw.println(info.dataDir);
+ pw.print(prefix); pw.print("packageList="); pw.println(pkgList);
+ if (instrumentationClass != null || instrumentationProfileFile != null
+ || instrumentationArguments != null) {
+ pw.print(prefix); pw.print("instrumentationClass=");
+ pw.print(instrumentationClass);
+ pw.print(" instrumentationProfileFile=");
+ pw.println(instrumentationProfileFile);
+ pw.print(prefix); pw.print("instrumentationArguments=");
+ pw.println(instrumentationArguments);
+ pw.print(prefix); pw.print("instrumentationInfo=");
+ pw.println(instrumentationInfo);
+ if (instrumentationInfo != null) {
+ instrumentationInfo.dump(new PrintWriterPrinter(pw), prefix + " ");
+ }
+ }
+ pw.print(prefix); pw.print("thread="); pw.print(thread);
+ pw.print(" curReceiver="); pw.println(curReceiver);
+ pw.print(prefix); pw.print("pid="); pw.print(pid); pw.print(" starting=");
+ pw.print(starting); pw.print(" lastPss="); pw.println(lastPss);
+ pw.print(prefix); pw.print("oom: max="); pw.print(maxAdj);
+ pw.print(" hidden="); pw.print(hiddenAdj);
+ pw.print(" curRaw="); pw.print(curRawAdj);
+ pw.print(" setRaw="); pw.print(setRawAdj);
+ pw.print(" cur="); pw.print(curAdj);
+ pw.print(" set="); pw.println(setAdj);
+ pw.print(prefix); pw.print("isForeground="); pw.print(isForeground);
+ pw.print(" setIsForeground="); pw.print(setIsForeground);
+ pw.print(" foregroundServices="); pw.print(foregroundServices);
+ pw.print(" forcingToForeground="); pw.println(forcingToForeground);
+ pw.print(prefix); pw.print("persistent="); pw.print(persistent);
+ pw.print(" removed="); pw.print(removed);
+ pw.print(" persistentActivities="); pw.println(persistentActivities);
+ if (debugging || crashing || crashDialog != null || notResponding
+ || anrDialog != null || bad) {
+ pw.print(prefix); pw.print("debugging="); pw.print(debugging);
+ pw.print(" crashing="); pw.print(crashing);
+ pw.print(" "); pw.print(crashDialog);
+ pw.print(" notResponding="); pw.print(notResponding);
+ pw.print(" " ); pw.print(anrDialog);
+ pw.print(" bad="); pw.println(bad);
+ }
+ if (activities.size() > 0) {
+ pw.print(prefix); pw.print("activities="); pw.println(activities);
+ }
+ if (services.size() > 0) {
+ pw.print(prefix); pw.print("services="); pw.println(services);
+ }
+ if (executingServices.size() > 0) {
+ pw.print(prefix); pw.print("executingServices="); pw.println(executingServices);
+ }
+ if (connections.size() > 0) {
+ pw.print(prefix); pw.print("connections="); pw.println(connections);
+ }
+ if (pubProviders.size() > 0) {
+ pw.print(prefix); pw.print("pubProviders="); pw.println(pubProviders);
+ }
+ if (conProviders.size() > 0) {
+ pw.print(prefix); pw.print("conProviders="); pw.println(conProviders);
+ }
+ if (receivers.size() > 0) {
+ pw.print(prefix); pw.print("receivers="); pw.println(receivers);
+ }
}
ProcessRecord(BatteryStatsImpl.Uid.Proc _batteryStats, IApplicationThread _thread,
@@ -154,6 +198,11 @@
persistentActivities = 0;
}
+ public void setPid(int _pid) {
+ pid = _pid;
+ stringName = null;
+ }
+
/**
* This method returns true if any of the activities within the process record are interesting
* to the user. See HistoryRecord.isInterestingToUserLocked()
@@ -188,9 +237,20 @@
}
public String toString() {
- return "ProcessRecord{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + pid + ":" + processName + "/" + info.uid + "}";
+ if (stringName != null) {
+ return stringName;
+ }
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("ProcessRecord{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(' ');
+ sb.append(pid);
+ sb.append(':');
+ sb.append(processName);
+ sb.append('/');
+ sb.append(info.uid);
+ sb.append('}');
+ return stringName = sb.toString();
}
/*
diff --git a/services/java/com/android/server/am/ReceiverList.java b/services/java/com/android/server/am/ReceiverList.java
index 6ac527b..0facefc 100644
--- a/services/java/com/android/server/am/ReceiverList.java
+++ b/services/java/com/android/server/am/ReceiverList.java
@@ -18,9 +18,12 @@
import android.app.IIntentReceiver;
import android.content.Intent;
+import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.PrintWriterPrinter;
+import android.util.Printer;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -39,6 +42,8 @@
BroadcastRecord curBroadcast = null;
boolean linkedToDeath = false;
+ String stringName;
+
ReceiverList(ActivityManagerService _owner, ProcessRecord _app,
int _pid, int _uid, IIntentReceiver _receiver) {
owner = _owner;
@@ -62,31 +67,45 @@
}
void dumpLocal(PrintWriter pw, String prefix) {
- pw.println(prefix + "receiver=IBinder "
- + Integer.toHexString(System.identityHashCode(receiver.asBinder())));
- pw.println(prefix + "app=" + app + " pid=" + pid + " uid=" + uid);
- pw.println(prefix + "curBroadcast=" + curBroadcast
- + " linkedToDeath=" + linkedToDeath);
+ pw.print(prefix); pw.print("app="); pw.print(app);
+ pw.print(" pid="); pw.print(pid); pw.print(" uid="); pw.println(uid);
+ if (curBroadcast != null || linkedToDeath) {
+ pw.print(prefix); pw.print("curBroadcast="); pw.print(curBroadcast);
+ pw.print(" linkedToDeath="); pw.println(linkedToDeath);
+ }
}
void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + this);
+ Printer pr = new PrintWriterPrinter(pw);
dumpLocal(pw, prefix);
String p2 = prefix + " ";
final int N = size();
for (int i=0; i<N; i++) {
BroadcastFilter bf = get(i);
- pw.println(prefix + "Filter #" + i + ": " + bf);
- bf.dump(pw, p2);
+ pw.print(prefix); pw.print("Filter #"); pw.print(i);
+ pw.print(": BroadcastFilter{");
+ pw.print(Integer.toHexString(System.identityHashCode(bf)));
+ pw.println('}');
+ bf.dumpInReceiverList(pw, pr, p2);
}
}
public String toString() {
- return "ReceiverList{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + pid + " " + (app != null ? app.processName : "(unknown name)")
- + "/" + uid + " client "
- + Integer.toHexString(System.identityHashCode(receiver.asBinder()))
- + "}";
+ if (stringName != null) {
+ return stringName;
+ }
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("ReceiverList{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(' ');
+ sb.append(pid);
+ sb.append(' ');
+ sb.append((app != null ? app.processName : "(unknown name)"));
+ sb.append('/');
+ sb.append(uid);
+ sb.append((receiver.asBinder() instanceof Binder) ? " local:" : " remote:");
+ sb.append(Integer.toHexString(System.identityHashCode(receiver.asBinder())));
+ sb.append('}');
+ return stringName = sb.toString();
}
}
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 4b90600..fc93b69 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -77,41 +77,49 @@
long restartTime; // time of last restart.
long nextRestartTime; // time when restartDelay will expire.
+ String stringName; // caching of toString
+
void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + this);
- pw.println(prefix + "intent=" + intent.getIntent());
- pw.println(prefix + "packageName=" + packageName);
- pw.println(prefix + "processName=" + processName);
- pw.println(prefix + "permission=" + permission);
- pw.println(prefix + "baseDir=" + baseDir+ " resDir=" + resDir + " dataDir=" + dataDir);
- pw.println(prefix + "app=" + app);
- pw.println(prefix + "isForeground=" + isForeground
- + " lastActivity=" + lastActivity);
- pw.println(prefix + "startRequested=" + startRequested
- + " startId=" + lastStartId
- + " executeNesting=" + executeNesting
- + " executingStart=" + executingStart
- + " crashCount=" + crashCount);
- pw.println(prefix + "totalRestartCount=" + totalRestartCount
- + " restartCount=" + restartCount
- + " restartDelay=" + restartDelay
- + " restartTime=" + restartTime
- + " nextRestartTime=" + nextRestartTime);
+ pw.print(prefix); pw.print("intent={");
+ pw.print(intent.getIntent().toShortString(true, false));
+ pw.println('}');
+ pw.print(prefix); pw.print("packageName="); pw.println(packageName);
+ pw.print(prefix); pw.print("processName="); pw.println(processName);
+ if (permission != null) {
+ pw.print(prefix); pw.print("permission="); pw.println(permission);
+ }
+ pw.print(prefix); pw.print("baseDir="); pw.print(baseDir);
+ if (!resDir.equals(baseDir)) pw.print(" resDir="); pw.print(resDir);
+ pw.print(" dataDir="); pw.println(dataDir);
+ pw.print(prefix); pw.print("app="); pw.println(app);
+ pw.print(prefix); pw.print("isForeground="); pw.print(isForeground);
+ pw.print(" lastActivity="); pw.println(lastActivity);
+ pw.print(prefix); pw.print("startRequested="); pw.print(startRequested);
+ pw.print(" startId="); pw.print(lastStartId);
+ pw.print(" executeNesting="); pw.print(executeNesting);
+ pw.print(" executingStart="); pw.print(executingStart);
+ pw.print(" crashCount="); pw.println(crashCount);
+ pw.print(prefix); pw.print("totalRestartCount="); pw.print(totalRestartCount);
+ pw.print(" restartCount="); pw.print(restartCount);
+ pw.print(" restartDelay="); pw.print(restartDelay);
+ pw.print(" restartTime="); pw.print(restartTime);
+ pw.print(" nextRestartTime="); pw.println(nextRestartTime);
if (bindings.size() > 0) {
- pw.println(prefix + "Bindings:");
Iterator<IntentBindRecord> it = bindings.values().iterator();
while (it.hasNext()) {
IntentBindRecord b = it.next();
- pw.println(prefix + "Binding " + b);
- b.dump(pw, prefix + " ");
+ pw.print(prefix); pw.print("* IntentBindRecord{");
+ pw.print(Integer.toHexString(System.identityHashCode(b)));
+ pw.println("}:");
+ b.dumpInService(pw, prefix + " ");
}
}
if (connections.size() > 0) {
- pw.println(prefix + "All Connections:");
+ pw.print(prefix); pw.println("All Connections:");
Iterator<ConnectionRecord> it = connections.values().iterator();
while (it.hasNext()) {
ConnectionRecord c = it.next();
- pw.println(prefix + " " + c);
+ pw.print(prefix); pw.print(" "); pw.println(c);
}
}
}
@@ -159,8 +167,13 @@
}
public String toString() {
- return "ServiceRecord{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + shortName + "}";
+ if (stringName != null) {
+ return stringName;
+ }
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("ServiceRecord{")
+ .append(Integer.toHexString(System.identityHashCode(this)))
+ .append(' ').append(shortName).append('}');
+ return stringName = sb.toString();
}
}
diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java
index aab3736..bcb8f54 100644
--- a/services/java/com/android/server/am/TaskRecord.java
+++ b/services/java/com/android/server/am/TaskRecord.java
@@ -36,6 +36,8 @@
boolean rootWasReset; // True if the intent at the root of the task had
// the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
+ String stringName; // caching of toString() result.
+
TaskRecord(int _taskId, ActivityInfo info, Intent _intent,
boolean _clearOnBackground) {
taskId = _taskId;
@@ -53,6 +55,8 @@
}
void setIntent(Intent _intent, ActivityInfo info) {
+ stringName = null;
+
if (info.targetActivity == null) {
intent = _intent;
realActivity = _intent != null ? _intent.getComponent() : null;
@@ -82,23 +86,63 @@
}
void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + this);
- pw.println(prefix + "clearOnBackground=" + clearOnBackground
- + " numActivities=" + numActivities
- + " rootWasReset=" + rootWasReset);
- pw.println(prefix + "affinity=" + affinity);
- pw.println(prefix + "intent=" + intent);
- pw.println(prefix + "affinityIntent=" + affinityIntent);
- pw.println(prefix + "origActivity=" + origActivity);
- pw.println(prefix + "lastActiveTime=" + lastActiveTime
- +" (inactive for " + (getInactiveDuration()/1000) + "s)");
+ if (clearOnBackground || numActivities != 0 || rootWasReset) {
+ pw.print(prefix); pw.print("clearOnBackground="); pw.print(clearOnBackground);
+ pw.print(" numActivities="); pw.print(numActivities);
+ pw.print(" rootWasReset="); pw.println(rootWasReset);
+ }
+ if (affinity != null) {
+ pw.print(prefix); pw.print("affinity="); pw.println(affinity);
+ }
+ if (intent != null) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append(prefix); sb.append("intent={");
+ intent.toShortString(sb, true, false);
+ sb.append('}');
+ pw.println(sb.toString());
+ }
+ if (affinityIntent != null) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append(prefix); sb.append("affinityIntent={");
+ affinityIntent.toShortString(sb, true, false);
+ sb.append('}');
+ pw.println(sb.toString());
+ }
+ if (origActivity != null) {
+ pw.print(prefix); pw.print("origActivity=");
+ pw.println(origActivity.flattenToShortString());
+ }
+ if (realActivity != null) {
+ pw.print(prefix); pw.print("realActivity=");
+ pw.println(realActivity.flattenToShortString());
+ }
+ pw.print(prefix); pw.print("lastActiveTime="); pw.print(lastActiveTime);
+ pw.print(" (inactive for ");
+ pw.print((getInactiveDuration()/1000)); pw.println("s)");
}
public String toString() {
- return "Task{" + taskId + " "
- + (affinity != null ? affinity
- : (intent != null ? intent.getComponent().flattenToShortString()
- : affinityIntent != null ? affinityIntent.getComponent().flattenToShortString() : "??"))
- + "}";
+ if (stringName != null) {
+ return stringName;
+ }
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("TaskRecord{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(" #");
+ sb.append(taskId);
+ if (affinity != null) {
+ sb.append(" A ");
+ sb.append(affinity);
+ } else if (intent != null) {
+ sb.append(" I ");
+ sb.append(intent.getComponent().flattenToShortString());
+ } else if (affinityIntent != null) {
+ sb.append(" aI ");
+ sb.append(affinityIntent.getComponent().flattenToShortString());
+ } else {
+ sb.append(" ??");
+ }
+ sb.append('}');
+ return stringName = sb.toString();
}
}
diff --git a/services/java/com/android/server/am/UriPermission.java b/services/java/com/android/server/am/UriPermission.java
index fb7a745..ffa8a2a 100644
--- a/services/java/com/android/server/am/UriPermission.java
+++ b/services/java/com/android/server/am/UriPermission.java
@@ -30,6 +30,8 @@
final HashSet<HistoryRecord> readActivities = new HashSet<HistoryRecord>();
final HashSet<HistoryRecord> writeActivities = new HashSet<HistoryRecord>();
+ String stringName;
+
UriPermission(int _uid, Uri _uri) {
uid = _uid;
uri = _uri;
@@ -65,18 +67,29 @@
}
public String toString() {
- return "UriPermission{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + uri + "}";
+ if (stringName != null) {
+ return stringName;
+ }
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("UriPermission{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(' ');
+ sb.append(uri);
+ sb.append('}');
+ return stringName = sb.toString();
}
void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + this);
- pw.println(prefix + " modeFlags=0x" + Integer.toHexString(modeFlags)
- + " uid=" + uid
- + " globalModeFlags=0x"
- + Integer.toHexString(globalModeFlags));
- pw.println(prefix + " readActivities=" + readActivities);
- pw.println(prefix + " writeActivities=" + writeActivities);
+ pw.print(prefix); pw.print("modeFlags=0x");
+ pw.print(Integer.toHexString(modeFlags));
+ pw.print(" uid="); pw.print(uid);
+ pw.print(" globalModeFlags=0x");
+ pw.println(Integer.toHexString(globalModeFlags));
+ if (readActivities.size() != 0) {
+ pw.print(prefix); pw.print("readActivities="); pw.println(readActivities);
+ }
+ if (writeActivities.size() != 0) {
+ pw.print(prefix); pw.print("writeActivities="); pw.println(writeActivities);
+ }
}
}
diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/java/com/android/server/am/UsageStatsService.java
index 3922f39..866334b 100755
--- a/services/java/com/android/server/am/UsageStatsService.java
+++ b/services/java/com/android/server/am/UsageStatsService.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import com.android.internal.app.IUsageStats;
+
import android.content.ComponentName;
import android.content.Context;
import android.os.Binder;
@@ -37,11 +38,11 @@
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
-import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.TimeZone;
/**
* This service collects the statistics associated with usage
@@ -53,6 +54,23 @@
public static final String SERVICE_NAME = "usagestats";
private static final boolean localLOGV = false;
private static final String TAG = "UsageStats";
+
+ // Current on-disk Parcel version
+ private static final int VERSION = 1004;
+
+ private static final int CHECKIN_VERSION = 3;
+
+ private static final String FILE_PREFIX = "usage-";
+
+ private static final int FILE_WRITE_INTERVAL = 30*60*1000; //ms
+
+ private static final int MAX_NUM_FILES = 5;
+
+ private static final int NUM_LAUNCH_TIME_BINS = 10;
+ private static final int[] LAUNCH_TIME_BINS = {
+ 250, 500, 750, 1000, 1500, 2000, 3000, 4000, 5000
+ };
+
static IUsageStats sService;
private Context mContext;
// structure used to maintain statistics since the last checkin.
@@ -66,16 +84,48 @@
// Order of locks is mFileLock followed by mStatsLock to avoid deadlocks
private String mResumedPkg;
private File mFile;
+ private String mFileLeaf;
//private File mBackupFile;
- private long mLastWriteRealTime;
- private int _FILE_WRITE_INTERVAL = 30*60*1000; //ms
- private static final String _PREFIX_DELIMIT=".";
- private String mFilePrefix;
+ private long mLastWriteElapsedTime;
+ private File mDir;
private Calendar mCal;
- private static final int _MAX_NUM_FILES = 10;
- private long mLastTime;
+ private int mLastWriteDay;
+
+ static class TimeStats {
+ int[] times = new int[NUM_LAUNCH_TIME_BINS];
+
+ TimeStats() {
+ }
+
+ void add(int val) {
+ final int[] bins = LAUNCH_TIME_BINS;
+ for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) {
+ if (val < bins[i]) {
+ times[i]++;
+ return;
+ }
+ }
+ times[NUM_LAUNCH_TIME_BINS-1]++;
+ }
+
+ TimeStats(Parcel in) {
+ final int[] localTimes = times;
+ for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
+ localTimes[i] = in.readInt();
+ }
+ }
+
+ void writeToParcel(Parcel out) {
+ final int[] localTimes = times;
+ for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
+ out.writeInt(localTimes[i]);
+ }
+ }
+ }
private class PkgUsageStatsExtended {
+ final HashMap<String, TimeStats> mLaunchTimes
+ = new HashMap<String, TimeStats>();
int mLaunchCount;
long mUsageTime;
long mPausedTime;
@@ -85,44 +135,106 @@
mLaunchCount = 0;
mUsageTime = 0;
}
+
+ PkgUsageStatsExtended(Parcel in) {
+ mLaunchCount = in.readInt();
+ mUsageTime = in.readLong();
+ if (localLOGV) Log.v(TAG, "Launch count: " + mLaunchCount
+ + ", Usage time:" + mUsageTime);
+
+ final int N = in.readInt();
+ if (localLOGV) Log.v(TAG, "Reading comps: " + N);
+ for (int i=0; i<N; i++) {
+ String comp = in.readString();
+ if (localLOGV) Log.v(TAG, "Component: " + comp);
+ TimeStats times = new TimeStats(in);
+ mLaunchTimes.put(comp, times);
+ }
+ }
+
void updateResume() {
mLaunchCount ++;
mResumedTime = SystemClock.elapsedRealtime();
}
+
void updatePause() {
mPausedTime = SystemClock.elapsedRealtime();
mUsageTime += (mPausedTime - mResumedTime);
}
+
+ void addLaunchTime(String comp, int millis) {
+ TimeStats times = mLaunchTimes.get(comp);
+ if (times == null) {
+ times = new TimeStats();
+ mLaunchTimes.put(comp, times);
+ }
+ times.add(millis);
+ }
+
+ void writeToParcel(Parcel out) {
+ out.writeInt(mLaunchCount);
+ out.writeLong(mUsageTime);
+ final int N = mLaunchTimes.size();
+ out.writeInt(N);
+ if (N > 0) {
+ for (Map.Entry<String, TimeStats> ent : mLaunchTimes.entrySet()) {
+ out.writeString(ent.getKey());
+ TimeStats times = ent.getValue();
+ times.writeToParcel(out);
+ }
+ }
+ }
+
void clear() {
+ mLaunchTimes.clear();
mLaunchCount = 0;
mUsageTime = 0;
}
}
- UsageStatsService(String fileName) {
+ UsageStatsService(String dir) {
mStats = new HashMap<String, PkgUsageStatsExtended>();
mStatsLock = new Object();
mFileLock = new Object();
- mFilePrefix = fileName;
- mCal = Calendar.getInstance();
+ mDir = new File(dir);
+ mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
+
+ mDir.mkdir();
+
+ // Remove any old usage files from previous versions.
+ File parentDir = mDir.getParentFile();
+ String fList[] = parentDir.list();
+ if (fList != null) {
+ String prefix = mDir.getName() + ".";
+ int i = fList.length;
+ while (i > 0) {
+ i--;
+ if (fList[i].startsWith(prefix)) {
+ Log.i(TAG, "Deleting old usage file: " + fList[i]);
+ (new File(parentDir, fList[i])).delete();
+ }
+ }
+ }
+
// Update current stats which are binned by date
- String uFileName = getCurrentDateStr(mFilePrefix);
- mFile = new File(uFileName);
+ mFileLeaf = getCurrentDateStr(FILE_PREFIX);
+ mFile = new File(mDir, mFileLeaf);
readStatsFromFile();
- mLastWriteRealTime = SystemClock.elapsedRealtime();
- mLastTime = new Date().getTime();
+ mLastWriteElapsedTime = SystemClock.elapsedRealtime();
+ // mCal was set by getCurrentDateStr(), want to use that same time.
+ mLastWriteDay = mCal.get(Calendar.DAY_OF_YEAR);
}
/*
* Utility method to convert date into string.
*/
private String getCurrentDateStr(String prefix) {
- mCal.setTime(new Date());
+ mCal.setTimeInMillis(System.currentTimeMillis());
StringBuilder sb = new StringBuilder();
if (prefix != null) {
sb.append(prefix);
- sb.append(".");
}
+ sb.append(mCal.get(Calendar.YEAR));
int mm = mCal.get(Calendar.MONTH) - Calendar.JANUARY +1;
if (mm < 10) {
sb.append("0");
@@ -133,7 +245,6 @@
sb.append("0");
}
sb.append(dd);
- sb.append(mCal.get(Calendar.YEAR));
return sb.toString();
}
@@ -166,11 +277,20 @@
private void readStatsFLOCK(File file) throws IOException {
Parcel in = getParcelForFile(file);
- while (in.dataAvail() > 0) {
+ int vers = in.readInt();
+ if (vers != VERSION) {
+ Log.w(TAG, "Usage stats version changed; dropping");
+ return;
+ }
+ int N = in.readInt();
+ while (N > 0) {
+ N--;
String pkgName = in.readString();
- PkgUsageStatsExtended pus = new PkgUsageStatsExtended();
- pus.mLaunchCount = in.readInt();
- pus.mUsageTime = in.readLong();
+ if (pkgName == null) {
+ break;
+ }
+ if (localLOGV) Log.v(TAG, "Reading package #" + N + ": " + pkgName);
+ PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in);
synchronized (mStatsLock) {
mStats.put(pkgName, pus);
}
@@ -178,27 +298,18 @@
}
private ArrayList<String> getUsageStatsFileListFLOCK() {
- File dir = getUsageFilesDir();
- if (dir == null) {
- Log.w(TAG, "Couldnt find writable directory for usage stats file");
- return null;
- }
// Check if there are too many files in the system and delete older files
- String fList[] = dir.list();
+ String fList[] = mDir.list();
if (fList == null) {
return null;
}
- File pre = new File(mFilePrefix);
- String filePrefix = pre.getName();
- // file name followed by dot
- int prefixLen = filePrefix.length()+1;
ArrayList<String> fileList = new ArrayList<String>();
for (String file : fList) {
- int index = file.indexOf(filePrefix);
- if (index == -1) {
+ if (!file.startsWith(FILE_PREFIX)) {
continue;
}
if (file.endsWith(".bak")) {
+ (new File(mDir, file)).delete();
continue;
}
fileList.add(file);
@@ -206,20 +317,7 @@
return fileList;
}
- private File getUsageFilesDir() {
- if (mFilePrefix == null) {
- return null;
- }
- File pre = new File(mFilePrefix);
- return new File(pre.getParent());
- }
-
private void checkFileLimitFLOCK() {
- File dir = getUsageFilesDir();
- if (dir == null) {
- Log.w(TAG, "Couldnt find writable directory for usage stats file");
- return;
- }
// Get all usage stats output files
ArrayList<String> fileList = getUsageStatsFileListFLOCK();
if (fileList == null) {
@@ -227,49 +325,54 @@
return;
}
int count = fileList.size();
- if (count <= _MAX_NUM_FILES) {
+ if (count <= MAX_NUM_FILES) {
return;
}
// Sort files
Collections.sort(fileList);
- count -= _MAX_NUM_FILES;
+ count -= MAX_NUM_FILES;
// Delete older files
for (int i = 0; i < count; i++) {
String fileName = fileList.get(i);
- File file = new File(dir, fileName);
- Log.i(TAG, "Deleting file : "+fileName);
+ File file = new File(mDir, fileName);
+ Log.i(TAG, "Deleting usage file : " + fileName);
file.delete();
}
}
- private void writeStatsToFile() {
+ private void writeStatsToFile(boolean force) {
synchronized (mFileLock) {
- long currTime = new Date().getTime();
- boolean dayChanged = ((currTime - mLastTime) >= (24*60*60*1000));
- long currRealTime = SystemClock.elapsedRealtime();
- if (((currRealTime-mLastWriteRealTime) < _FILE_WRITE_INTERVAL) &&
- (!dayChanged)) {
- // wait till the next update
- return;
+ mCal.setTimeInMillis(System.currentTimeMillis());
+ final int curDay = mCal.get(Calendar.DAY_OF_YEAR);
+ // Determine if the day changed... note that this will be wrong
+ // if the year has changed but we are in the same day of year...
+ // we can probably live with this.
+ final boolean dayChanged = curDay != mLastWriteDay;
+ long currElapsedTime = SystemClock.elapsedRealtime();
+ if (!force) {
+ if (((currElapsedTime-mLastWriteElapsedTime) < FILE_WRITE_INTERVAL) &&
+ (!dayChanged)) {
+ // wait till the next update
+ return;
+ }
}
// Get the most recent file
- String todayStr = getCurrentDateStr(mFilePrefix);
+ mFileLeaf = getCurrentDateStr(FILE_PREFIX);
// Copy current file to back up
File backupFile = new File(mFile.getPath() + ".bak");
mFile.renameTo(backupFile);
try {
- checkFileLimitFLOCK();
- mFile.createNewFile();
// Write mStats to file
writeStatsFLOCK();
- mLastWriteRealTime = currRealTime;
- mLastTime = currTime;
+ mLastWriteElapsedTime = currElapsedTime;
if (dayChanged) {
+ mLastWriteDay = curDay;
// clear stats
synchronized (mStats) {
mStats.clear();
}
- mFile = new File(todayStr);
+ mFile = new File(mDir, mFileLeaf);
+ checkFileLimitFLOCK();
}
// Delete the backup file
if (backupFile != null) {
@@ -278,6 +381,7 @@
} catch (IOException e) {
Log.w(TAG, "Failed writing stats to file:" + mFile);
if (backupFile != null) {
+ mFile.delete();
backupFile.renameTo(mFile);
}
}
@@ -286,22 +390,26 @@
private void writeStatsFLOCK() throws IOException {
FileOutputStream stream = new FileOutputStream(mFile);
- Parcel out = Parcel.obtain();
- writeStatsToParcelFLOCK(out);
- stream.write(out.marshall());
- out.recycle();
- stream.flush();
- stream.close();
+ try {
+ Parcel out = Parcel.obtain();
+ writeStatsToParcelFLOCK(out);
+ stream.write(out.marshall());
+ out.recycle();
+ stream.flush();
+ } finally {
+ stream.close();
+ }
}
private void writeStatsToParcelFLOCK(Parcel out) {
synchronized (mStatsLock) {
+ out.writeInt(VERSION);
Set<String> keys = mStats.keySet();
+ out.writeInt(keys.size());
for (String key : keys) {
PkgUsageStatsExtended pus = mStats.get(key);
out.writeString(key);
- out.writeInt(pus.mLaunchCount);
- out.writeLong(pus.mUsageTime);
+ pus.writeToParcel(out);
}
}
}
@@ -311,6 +419,11 @@
ServiceManager.addService(SERVICE_NAME, asBinder());
}
+ public void shutdown() {
+ Log.w(TAG, "Writing usage stats before shutdown...");
+ writeStatsToFile(true);
+ }
+
public static IUsageStats getService() {
if (sService != null) {
return sService;
@@ -355,6 +468,10 @@
return;
}
if (localLOGV) Log.i(TAG, "paused component:"+pkgName);
+
+ // Persist current data to file if needed.
+ writeStatsToFile(false);
+
synchronized (mStatsLock) {
PkgUsageStatsExtended pus = mStats.get(pkgName);
if (pus == null) {
@@ -364,8 +481,25 @@
}
pus.updatePause();
}
- // Persist data to file
- writeStatsToFile();
+ }
+
+ public void noteLaunchTime(ComponentName componentName, int millis) {
+ enforceCallingPermission();
+ String pkgName;
+ if ((componentName == null) ||
+ ((pkgName = componentName.getPackageName()) == null)) {
+ return;
+ }
+
+ // Persist current data to file if needed.
+ writeStatsToFile(false);
+
+ synchronized (mStatsLock) {
+ PkgUsageStatsExtended pus = mStats.get(pkgName);
+ if (pus != null) {
+ pus.addLaunchTime(componentName.getClassName(), millis);
+ }
+ }
}
public void enforceCallingPermission() {
@@ -432,27 +566,25 @@
}
}
- private void collectDumpInfoFLOCK(PrintWriter pw, String[] args) {
+ private void collectDumpInfoFLOCK(PrintWriter pw, boolean isCompactOutput,
+ boolean deleteAfterPrint) {
List<String> fileList = getUsageStatsFileListFLOCK();
if (fileList == null) {
return;
}
- final boolean isCheckinRequest = scanArgs(args, "-c");
Collections.sort(fileList);
- File usageFile = new File(mFilePrefix);
- String dirName = usageFile.getParent();
- File dir = new File(dirName);
- String filePrefix = usageFile.getName();
- // file name followed by dot
- int prefixLen = filePrefix.length()+1;
- String todayStr = getCurrentDateStr(null);
for (String file : fileList) {
- File dFile = new File(dir, file);
- String dateStr = file.substring(prefixLen);
+ if (deleteAfterPrint && file.equalsIgnoreCase(mFileLeaf)) {
+ // In this mode we don't print the current day's stats, since
+ // they are incomplete.
+ continue;
+ }
+ File dFile = new File(mDir, file);
+ String dateStr = file.substring(FILE_PREFIX.length());
try {
Parcel in = getParcelForFile(dFile);
- collectDumpInfoFromParcelFLOCK(in, pw, dateStr, isCheckinRequest);
- if (isCheckinRequest && !todayStr.equalsIgnoreCase(dateStr)) {
+ collectDumpInfoFromParcelFLOCK(in, pw, dateStr, isCompactOutput);
+ if (deleteAfterPrint) {
// Delete old file after collecting info only for checkin requests
dFile.delete();
}
@@ -466,40 +598,101 @@
}
private void collectDumpInfoFromParcelFLOCK(Parcel in, PrintWriter pw,
- String date, boolean isCheckinRequest) {
- StringBuilder sb = new StringBuilder();
- sb.append("Date:");
- sb.append(date);
- boolean first = true;
- while (in.dataAvail() > 0) {
- String pkgName = in.readString();
- int launchCount = in.readInt();
- long usageTime = in.readLong();
- if (isCheckinRequest) {
- if (!first) {
- sb.append(",");
- }
- sb.append(pkgName);
- sb.append(",");
- sb.append(launchCount);
- sb.append(",");
- sb.append(usageTime);
- sb.append("ms");
- } else {
- if (first) {
- sb.append("\n");
- }
- sb.append("pkg=");
- sb.append(pkgName);
- sb.append(", launchCount=");
- sb.append(launchCount);
- sb.append(", usageTime=");
- sb.append(usageTime);
- sb.append(" ms\n");
- }
- first = false;
+ String date, boolean isCompactOutput) {
+ StringBuilder sb = new StringBuilder(512);
+ if (isCompactOutput) {
+ sb.append("D:");
+ sb.append(CHECKIN_VERSION);
+ sb.append(',');
+ } else {
+ sb.append("Date: ");
}
- pw.write(sb.toString());
+
+ sb.append(date);
+
+ int vers = in.readInt();
+ if (vers != VERSION) {
+ sb.append(" (old data version)");
+ pw.println(sb.toString());
+ return;
+ }
+
+ pw.println(sb.toString());
+ int N = in.readInt();
+
+ while (N > 0) {
+ N--;
+ String pkgName = in.readString();
+ if (pkgName == null) {
+ break;
+ }
+ sb.setLength(0);
+ PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in);
+ if (isCompactOutput) {
+ sb.append("P:");
+ sb.append(pkgName);
+ sb.append(",");
+ sb.append(pus.mLaunchCount);
+ sb.append(",");
+ sb.append(pus.mUsageTime);
+ sb.append('\n');
+ final int NC = pus.mLaunchTimes.size();
+ if (NC > 0) {
+ for (Map.Entry<String, TimeStats> ent : pus.mLaunchTimes.entrySet()) {
+ sb.append("A:");
+ sb.append(ent.getKey());
+ TimeStats times = ent.getValue();
+ for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
+ sb.append(",");
+ sb.append(times.times[i]);
+ }
+ sb.append('\n');
+ }
+ }
+
+ } else {
+ sb.append(" ");
+ sb.append(pkgName);
+ sb.append(": ");
+ sb.append(pus.mLaunchCount);
+ sb.append(" times, ");
+ sb.append(pus.mUsageTime);
+ sb.append(" ms");
+ sb.append('\n');
+ final int NC = pus.mLaunchTimes.size();
+ if (NC > 0) {
+ for (Map.Entry<String, TimeStats> ent : pus.mLaunchTimes.entrySet()) {
+ sb.append(" ");
+ sb.append(ent.getKey());
+ TimeStats times = ent.getValue();
+ int lastBin = 0;
+ boolean first = true;
+ for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) {
+ if (times.times[i] != 0) {
+ sb.append(first ? ": " : ", ");
+ sb.append(lastBin);
+ sb.append('-');
+ sb.append(LAUNCH_TIME_BINS[i]);
+ sb.append('=');
+ sb.append(times.times[i]);
+ first = false;
+ }
+ lastBin = LAUNCH_TIME_BINS[i];
+ }
+ if (times.times[NUM_LAUNCH_TIME_BINS-1] != 0) {
+ sb.append(first ? ": " : ", ");
+ sb.append(">=");
+ sb.append(lastBin);
+ sb.append('=');
+ sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]);
+ }
+ sb.append('\n');
+ }
+ }
+ }
+
+ pw.write(sb.toString());
+ }
}
/**
@@ -524,8 +717,19 @@
* The data persisted to file is parsed and the stats are computed.
*/
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ final boolean isCheckinRequest = scanArgs(args, "--checkin");
+ final boolean isCompactOutput = isCheckinRequest || scanArgs(args, "-c");
+ final boolean deleteAfterPrint = isCheckinRequest || scanArgs(args, "-d");
+
+ // Make sure the current stats are written to the file. This
+ // doesn't need to be done if we are deleting files after printing,
+ // since it that case we won't print the current stats.
+ if (!deleteAfterPrint) {
+ writeStatsToFile(true);
+ }
+
synchronized (mFileLock) {
- collectDumpInfoFLOCK(pw, args);
+ collectDumpInfoFLOCK(pw, isCompactOutput, deleteAfterPrint);
}
}
diff --git a/services/java/com/android/server/status/IconMerger.java b/services/java/com/android/server/status/IconMerger.java
index 37fdbfb..5b80638 100644
--- a/services/java/com/android/server/status/IconMerger.java
+++ b/services/java/com/android/server/status/IconMerger.java
@@ -8,8 +8,6 @@
public class IconMerger extends LinearLayout {
- private static final boolean SPEW = false;
-
StatusBarService service;
StatusBarIcon moreIcon;
@@ -29,7 +27,7 @@
int fitRight = -1;
for (i=N-1; i>=0; i--) {
final View child = getChildAt(i);
- if (child != null && child.getVisibility() != GONE) {
+ if (child.getVisibility() != GONE) {
fitRight = child.getRight();
break;
}
@@ -45,7 +43,7 @@
moreView = child;
startIndex = i+1;
}
- else if (child != null && child.getVisibility() != GONE) {
+ else if (child.getVisibility() != GONE) {
fitLeft = child.getLeft();
break;
}
@@ -71,7 +69,7 @@
int number = 0;
for (i=startIndex; i<N; i++) {
final View child = getChildAt(i);
- if (child != null && child.getVisibility() != GONE) {
+ if (child.getVisibility() != GONE) {
int childLeft = child.getLeft();
int childRight = child.getRight();
if (childLeft < breakingPoint) {
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index 713cd13..0b161d6 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -16,13 +16,6 @@
package com.android.server.status;
-import com.android.internal.R;
-import com.android.internal.app.IBatteryStats;
-import com.android.internal.location.GpsLocationProvider;
-import com.android.internal.telephony.SimCard;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.server.am.BatteryStatsService;
-
import android.app.AlertDialog;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothDevice;
@@ -59,6 +52,14 @@
import android.widget.LinearLayout;
import android.widget.TextView;
+import com.android.internal.R;
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.location.GpsLocationProvider;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.cdma.TtyIntent;
+import com.android.server.am.BatteryStatsService;
+
import java.util.Calendar;
import java.util.TimeZone;
@@ -110,7 +111,10 @@
// phone
private TelephonyManager mPhone;
private IBinder mPhoneIcon;
+
+ //***** Signal strength icons
private IconData mPhoneData;
+ //GSM/UMTS
private static final int[] sSignalImages = new int[] {
com.android.internal.R.drawable.stat_sys_signal_0,
com.android.internal.R.drawable.stat_sys_signal_1,
@@ -125,7 +129,32 @@
com.android.internal.R.drawable.stat_sys_r_signal_3,
com.android.internal.R.drawable.stat_sys_r_signal_4
};
+ //CDMA
+ private static final int[] sSignalImages_cdma = new int[] {
+ com.android.internal.R.drawable.stat_sys_signal_0_cdma,
+ com.android.internal.R.drawable.stat_sys_signal_1_cdma,
+ com.android.internal.R.drawable.stat_sys_signal_2_cdma,
+ com.android.internal.R.drawable.stat_sys_signal_3_cdma,
+ com.android.internal.R.drawable.stat_sys_signal_4_cdma
+ };
+ private static final int[] sSignalImages_r_cdma = new int[] {
+ com.android.internal.R.drawable.stat_sys_r_signal_0_cdma,
+ com.android.internal.R.drawable.stat_sys_r_signal_1_cdma,
+ com.android.internal.R.drawable.stat_sys_r_signal_2_cdma,
+ com.android.internal.R.drawable.stat_sys_r_signal_3_cdma,
+ com.android.internal.R.drawable.stat_sys_r_signal_4_cdma
+ };
+ private static final int[] sSignalImages_ra_cdma = new int[] {
+ com.android.internal.R.drawable.stat_sys_ra_signal_0_cdma,
+ com.android.internal.R.drawable.stat_sys_ra_signal_1_cdma,
+ com.android.internal.R.drawable.stat_sys_ra_signal_2_cdma,
+ com.android.internal.R.drawable.stat_sys_ra_signal_3_cdma,
+ com.android.internal.R.drawable.stat_sys_ra_signal_4_cdma
+ };
+
+ //***** Data connection icons
private int[] mDataIconList = sDataNetType_g;
+ //GSM/UMTS
private static final int[] sDataNetType_g = new int[] {
com.android.internal.R.drawable.stat_sys_data_connected_g,
com.android.internal.R.drawable.stat_sys_data_in_g,
@@ -144,12 +173,25 @@
com.android.internal.R.drawable.stat_sys_data_out_e,
com.android.internal.R.drawable.stat_sys_data_inandout_e,
};
+ //CDMA
+ private static final int[] sDataNetType_evdo = new int[] {
+ com.android.internal.R.drawable.stat_sys_data_connected_evdo,
+ com.android.internal.R.drawable.stat_sys_data_in_evdo,
+ com.android.internal.R.drawable.stat_sys_data_out_evdo,
+ com.android.internal.R.drawable.stat_sys_data_inandout_evdo,
+ };
+ private static final int[] sDataNetType_1xrtt = new int[] {
+ com.android.internal.R.drawable.stat_sys_data_connected_1xrtt,
+ com.android.internal.R.drawable.stat_sys_data_in_1xrtt,
+ com.android.internal.R.drawable.stat_sys_data_out_1xrtt,
+ com.android.internal.R.drawable.stat_sys_data_inandout_1xrtt,
+ };
+
// Assume it's all good unless we hear otherwise. We don't always seem
// to get broadcasts that it *is* there.
- SimCard.State mSimState = SimCard.State.READY;
+ IccCard.State mSimState = IccCard.State.READY;
int mPhoneState = TelephonyManager.CALL_STATE_IDLE;
int mDataState = TelephonyManager.DATA_DISCONNECTED;
- int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
ServiceState mServiceState;
int mSignalAsu = -1;
@@ -163,7 +205,7 @@
private IBinder mVolumeIcon;
private IconData mVolumeData;
private boolean mVolumeVisible;
-
+
// bluetooth device status
private IBinder mBluetoothIcon;
private IconData mBluetoothData;
@@ -202,6 +244,11 @@
private IBinder mSyncActiveIcon;
private IBinder mSyncFailingIcon;
+ // TTY mode
+ // Icon lit when TTY mode is enabled
+ private IBinder mTTYModeIcon;
+ private IconData mTTYModeEnableIconData;
+
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -250,6 +297,9 @@
else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
updateSimState(intent);
}
+ else if (action.equals(TtyIntent.TTY_ENABLED_CHANGE_ACTION)) {
+ updateTTY(intent);
+ }
}
};
@@ -294,7 +344,13 @@
mWifiIcon = service.addIcon(mWifiData, null);
service.setIconVisibility(mWifiIcon, false);
// wifi will get updated by the sticky intents
-
+
+ // TTY status
+ mTTYModeEnableIconData = IconData.makeIcon("tty",
+ null, com.android.internal.R.drawable.stat_sys_tty_mode, 0, 0);
+ mTTYModeIcon = service.addIcon(mTTYModeEnableIconData, null);
+ service.setIconVisibility(mTTYModeIcon, false);
+
// bluetooth status
mBluetoothData = IconData.makeIcon("bluetooth",
null, com.android.internal.R.drawable.stat_sys_data_bluetooth, 0, 0);
@@ -362,6 +418,7 @@
filter.addAction(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION);
filter.addAction(GpsLocationProvider.GPS_FIX_CHANGE_ACTION);
filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+ filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
}
@@ -506,7 +563,7 @@
com.android.internal.R.styleable.Theme);
lp.dimAmount = a.getFloat(android.R.styleable.Theme_backgroundDimAmount, 0.5f);
a.recycle();
-
+
lp.setTitle("Battery");
TextView levelTextView = (TextView)v.findViewById(com.android.internal.R.id.level_percent);
@@ -642,26 +699,26 @@
private final void updateSimState(Intent intent) {
- String stateExtra = intent.getStringExtra(SimCard.INTENT_KEY_SIM_STATE);
- if (SimCard.INTENT_VALUE_SIM_ABSENT.equals(stateExtra)) {
- mSimState = SimCard.State.ABSENT;
+ String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
+ if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
+ mSimState = IccCard.State.ABSENT;
}
- else if (SimCard.INTENT_VALUE_SIM_READY.equals(stateExtra)) {
- mSimState = SimCard.State.READY;
+ else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
+ mSimState = IccCard.State.READY;
}
- else if (SimCard.INTENT_VALUE_SIM_LOCKED.equals(stateExtra)) {
- final String lockedReason = intent.getStringExtra(SimCard.INTENT_KEY_LOCKED_REASON);
- if (SimCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
- mSimState = SimCard.State.PIN_REQUIRED;
+ else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
+ final String lockedReason = intent.getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON);
+ if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
+ mSimState = IccCard.State.PIN_REQUIRED;
}
- else if (SimCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
- mSimState = SimCard.State.PUK_REQUIRED;
+ else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
+ mSimState = IccCard.State.PUK_REQUIRED;
}
else {
- mSimState = SimCard.State.NETWORK_LOCKED;
+ mSimState = IccCard.State.NETWORK_LOCKED;
}
} else {
- mSimState = SimCard.State.UNKNOWN;
+ mSimState = IccCard.State.UNKNOWN;
}
updateDataIcon();
}
@@ -707,28 +764,54 @@
else asu = 1;
int[] iconList;
- if (mPhone.isNetworkRoaming()) {
+ if (mPhone.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
+ switch(ss.getExtendedCdmaRoaming()) {
+ case ServiceState.REGISTRATION_STATE_ROAMING:
+ iconList = this.sSignalImages_r_cdma;
+ break;
+ case ServiceState.REGISTRATION_STATE_ROAMING_AFFILIATE:
+ iconList = this.sSignalImages_ra_cdma;
+ break;
+ default:
+ iconList = this.sSignalImages_cdma;
+ break;
+ }
+ } else if (mPhone.isNetworkRoaming()) {
iconList = sSignalImages_r;
} else {
iconList = sSignalImages;
}
-
+
mPhoneData.iconId = iconList[asu];
mService.updateIcon(mPhoneIcon, mPhoneData, null);
}
private final void updateDataNetType() {
- mDataNetType = mPhone.getNetworkType();
- switch (mDataNetType) {
- case TelephonyManager.NETWORK_TYPE_EDGE:
- mDataIconList = sDataNetType_e;
- break;
- case TelephonyManager.NETWORK_TYPE_UMTS:
- mDataIconList = sDataNetType_3g;
- break;
- default:
- mDataIconList = sDataNetType_g;
- break;
+ int net = mPhone.getNetworkType();
+ ServiceState ss = this.mServiceState;
+
+ switch (net) {
+
+ case TelephonyManager.NETWORK_TYPE_EDGE:
+ mDataIconList = sDataNetType_e;
+ break;
+ case TelephonyManager.NETWORK_TYPE_UMTS:
+ mDataIconList = sDataNetType_3g;
+ break;
+ case TelephonyManager.NETWORK_TYPE_CDMA:
+ // display 1xRTT for IS95A/B
+ mDataIconList = this.sDataNetType_1xrtt;
+ break;
+ case TelephonyManager.NETWORK_TYPE_1xRTT:
+ mDataIconList = this.sDataNetType_1xrtt;
+ break;
+ case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
+ case TelephonyManager.NETWORK_TYPE_EVDO_A:
+ mDataIconList = sDataNetType_evdo;
+ break;
+ default:
+ mDataIconList = sDataNetType_g;
+ break;
}
}
@@ -736,9 +819,9 @@
int iconId;
boolean visible = true;
- if (mSimState == SimCard.State.READY || mSimState == SimCard.State.UNKNOWN) {
+ if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) {
int data = mDataState;
-
+
int[] list = mDataIconList;
ServiceState ss = mServiceState;
@@ -775,7 +858,7 @@
}
long ident = Binder.clearCallingIdentity();
try {
- mBatteryStats.notePhoneDataConnectionState(mDataNetType, visible);
+ mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
} catch (RemoteException e) {
} finally {
Binder.restoreCallingIdentity(ident);
@@ -865,10 +948,10 @@
} else {
iconId = sWifiSignalImages[mLastWifiSignalLevel];
}
-
+
// Show the icon since wi-fi is connected
mService.setIconVisibility(mWifiIcon, true);
-
+
} else {
mLastWifiSignalLevel = -1;
mIsWifiConnected = false;
@@ -914,6 +997,24 @@
}
}
+ private final void updateTTY(Intent intent) {
+ final String action = intent.getAction();
+ final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false);
+
+ Log.i(TAG, "updateTTY: enabled: " + enabled);
+
+ if (enabled) {
+ // TTY is on
+ Log.i(TAG, "updateTTY: set TTY on");
+ mService.updateIcon(mTTYModeIcon, mTTYModeEnableIconData, null);
+ mService.setIconVisibility(mTTYModeIcon, true);
+ } else {
+ // TTY is off
+ Log.i(TAG, "updateTTY: set TTY off");
+ mService.setIconVisibility(mTTYModeIcon, false);
+ }
+ }
+
private class StatusBarHandler extends Handler {
@Override
public void handleMessage(Message msg) {
@@ -927,3 +1028,6 @@
}
}
}
+
+
+