summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/input/InputReader.h3
-rw-r--r--services/java/Android.mk2
-rw-r--r--services/java/com/android/server/ConnectivityService.java12
-rw-r--r--services/java/com/android/server/DevicePolicyManagerService.java86
-rw-r--r--services/java/com/android/server/LocationManagerService.java75
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java83
-rw-r--r--services/java/com/android/server/am/ActivityStack.java2
-rw-r--r--services/java/com/android/server/am/ActivityStackSupervisor.java4
-rw-r--r--services/java/com/android/server/connectivity/PacManager.java230
-rw-r--r--services/java/com/android/server/content/SyncManager.java9
-rw-r--r--services/java/com/android/server/content/SyncStorageEngine.java439
-rw-r--r--services/java/com/android/server/display/WifiDisplayController.java22
-rw-r--r--services/java/com/android/server/dreams/DreamManagerService.java8
-rw-r--r--services/java/com/android/server/location/FlpHardwareProvider.java93
-rw-r--r--services/java/com/android/server/location/GeofenceProxy.java20
-rw-r--r--services/java/com/android/server/location/GpsLocationProvider.java118
-rwxr-xr-xservices/java/com/android/server/pm/PackageManagerService.java59
-rw-r--r--services/java/com/android/server/pm/PackageSetting.java6
-rw-r--r--services/java/com/android/server/pm/Settings.java19
-rw-r--r--services/java/com/android/server/print/RemotePrintService.java283
-rw-r--r--services/java/com/android/server/print/RemotePrintSpooler.java141
-rw-r--r--services/java/com/android/server/print/UserState.java72
-rw-r--r--services/java/com/android/server/wifi/WifiService.java170
-rw-r--r--services/jni/com_android_server_location_FlpHardwareProvider.cpp151
-rw-r--r--services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java13
25 files changed, 1485 insertions, 635 deletions
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 98daaf5..a8bb636 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -1285,6 +1285,9 @@ protected:
if (haveSizeBias) {
*outSize += sizeBias;
}
+ if (*outSize < 0) {
+ *outSize = 0;
+ }
}
} mCalibration;
diff --git a/services/java/Android.mk b/services/java/Android.mk
index 95b28d9..8c3d0f0 100644
--- a/services/java/Android.mk
+++ b/services/java/Android.mk
@@ -11,7 +11,7 @@ LOCAL_SRC_FILES := \
LOCAL_MODULE:= services
-LOCAL_JAVA_LIBRARIES := android.policy telephony-common
+LOCAL_JAVA_LIBRARIES := android.policy conscrypt telephony-common
include $(BUILD_JAVA_LIBRARY)
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index bb0d248..a0e6dd1 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -3916,13 +3916,13 @@ public class ConnectivityService extends IConnectivityManager.Stub {
Random rand = new Random();
mParams = params;
- try {
- if (mCs.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false) {
- log("isMobileOk: not mobile capable");
- result = ConnectivityManager.CMP_RESULT_CODE_NO_CONNECTION;
- return result;
- }
+ if (mCs.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false) {
+ log("isMobileOk: not mobile capable");
+ result = ConnectivityManager.CMP_RESULT_CODE_NO_CONNECTION;
+ return result;
+ }
+ try {
// Enable fail fast as we'll do retries here and use a
// hipri connection so the default connection stays active.
log("isMobileOk: start hipri url=" + params.mUrl);
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 43f95c3..7e83396 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -16,11 +16,14 @@
package com.android.server;
+import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
+
import com.android.internal.os.storage.ExternalStorageFormatter;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
import com.android.internal.util.XmlUtils;
import com.android.internal.widget.LockPatternUtils;
+import com.android.org.conscrypt.TrustedCertificateStore;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -49,6 +52,7 @@ import android.content.pm.Signature;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
@@ -66,7 +70,12 @@ import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.security.Credentials;
+import android.security.IKeyChainService;
+import android.security.KeyChain;
+import android.security.KeyChain.KeyChainConnection;
import android.util.AtomicFile;
+import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.Slog;
@@ -75,6 +84,7 @@ import android.util.Xml;
import android.view.IWindowManager;
import android.view.WindowManagerPolicy;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -82,8 +92,14 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
+import java.security.KeyStore.TrustedCertificateEntry;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@@ -1870,6 +1886,76 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return !"".equals(state);
}
+ public boolean installCaCert(byte[] certBuffer) throws RemoteException {
+ mContext.enforceCallingOrSelfPermission(MANAGE_CA_CERTIFICATES, null);
+ KeyChainConnection keyChainConnection = null;
+ byte[] pemCert;
+ try {
+ X509Certificate cert = parseCert(certBuffer);
+ pemCert = Credentials.convertToPem(cert);
+ } catch (CertificateException ce) {
+ Log.e(TAG, "Problem converting cert", ce);
+ return false;
+ } catch (IOException ioe) {
+ Log.e(TAG, "Problem reading cert", ioe);
+ return false;
+ }
+ try {
+ keyChainConnection = KeyChain.bind(mContext);
+ try {
+ keyChainConnection.getService().installCaCertificate(pemCert);
+ return true;
+ } finally {
+ if (keyChainConnection != null) {
+ keyChainConnection.close();
+ keyChainConnection = null;
+ }
+ }
+ } catch (InterruptedException e1) {
+ Log.w(TAG, "installCaCertsToKeyChain(): ", e1);
+ Thread.currentThread().interrupt();
+ }
+ return false;
+ }
+
+ private static X509Certificate parseCert(byte[] certBuffer)
+ throws CertificateException, IOException {
+ CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+ return (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(
+ certBuffer));
+ }
+
+ public void uninstallCaCert(final byte[] certBuffer) {
+ mContext.enforceCallingOrSelfPermission(MANAGE_CA_CERTIFICATES, null);
+ TrustedCertificateStore certStore = new TrustedCertificateStore();
+ String alias = null;
+ try {
+ X509Certificate cert = parseCert(certBuffer);
+ alias = certStore.getCertificateAlias(cert);
+ } catch (CertificateException ce) {
+ Log.e(TAG, "Problem creating X509Certificate", ce);
+ return;
+ } catch (IOException ioe) {
+ Log.e(TAG, "Problem reading certificate", ioe);
+ return;
+ }
+ try {
+ KeyChainConnection keyChainConnection = KeyChain.bind(mContext);
+ IKeyChainService service = keyChainConnection.getService();
+ try {
+ service.deleteCaCertificate(alias);
+ } catch (RemoteException e) {
+ Log.e(TAG, "from CaCertUninstaller: ", e);
+ } finally {
+ keyChainConnection.close();
+ keyChainConnection = null;
+ }
+ } catch (InterruptedException ie) {
+ Log.w(TAG, "CaCertUninstaller: ", ie);
+ Thread.currentThread().interrupt();
+ }
+ }
+
void wipeDataLocked(int flags) {
// If the SD card is encrypted and non-removable, we have to force a wipe.
boolean forceExtWipe = !Environment.isExternalStorageRemovable() && isExtStorageEncrypted();
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index a32699a..9761441 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -420,19 +420,7 @@ public class LocationManagerService extends ILocationManager.Stub {
Slog.e(TAG, "no geocoder provider found");
}
- // bind to geofence provider
- GeofenceProxy provider = GeofenceProxy.createAndBind(mContext,
- com.android.internal.R.bool.config_enableGeofenceOverlay,
- com.android.internal.R.string.config_geofenceProviderPackageName,
- com.android.internal.R.array.config_locationProviderPackageNames,
- mLocationHandler,
- gpsProvider.getGpsGeofenceProxy());
- if (provider == null) {
- Slog.e(TAG, "no geofence provider found");
- }
-
// bind to fused provider
- // TODO: [GeofenceIntegration] bind #getGeofenceHardware() with the GeofenceProxy
FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
FusedProxy fusedProxy = FusedProxy.createAndBind(
mContext,
@@ -441,10 +429,21 @@ public class LocationManagerService extends ILocationManager.Stub {
com.android.internal.R.bool.config_enableFusedLocationOverlay,
com.android.internal.R.string.config_fusedLocationProviderPackageName,
com.android.internal.R.array.config_locationProviderPackageNames);
-
if(fusedProxy == null) {
Slog.e(TAG, "No FusedProvider found.");
}
+
+ // bind to geofence provider
+ GeofenceProxy provider = GeofenceProxy.createAndBind(mContext,
+ com.android.internal.R.bool.config_enableGeofenceOverlay,
+ com.android.internal.R.string.config_geofenceProviderPackageName,
+ com.android.internal.R.array.config_locationProviderPackageNames,
+ mLocationHandler,
+ gpsProvider.getGpsGeofenceProxy(),
+ flpHardwareProvider.getGeofenceHardware());
+ if (provider == null) {
+ Slog.e(TAG, "no geofence provider found");
+ }
}
/**
@@ -549,30 +548,52 @@ public class LocationManagerService extends ILocationManager.Stub {
return s.toString();
}
+ /**
+ * Update AppOp monitoring for this receiver.
+ *
+ * @param allow If true receiver is currently active, if false it's been removed.
+ */
public void updateMonitoring(boolean allow) {
if (mHideFromAppOps) {
return;
}
+ boolean requestingLocation = false;
+ boolean requestingHighPowerLocation = false;
+ if (allow) {
+ // See if receiver has any enabled update records. Also note if any update records
+ // are high power (has a high power provider with an interval under a threshold).
+ for (UpdateRecord updateRecord : mUpdateRecords.values()) {
+ if (isAllowedByCurrentUserSettingsLocked(updateRecord.mProvider)) {
+ requestingLocation = true;
+ LocationProviderInterface locationProvider
+ = mProvidersByName.get(updateRecord.mProvider);
+ ProviderProperties properties = locationProvider != null
+ ? locationProvider.getProperties() : null;
+ if (properties != null
+ && properties.mPowerRequirement == Criteria.POWER_HIGH
+ && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
+ requestingHighPowerLocation = true;
+ break;
+ }
+ }
+ }
+ }
+
// First update monitoring of any location request (including high power).
- mOpMonitoring = updateMonitoring(allow, mOpMonitoring,
+ mOpMonitoring = updateMonitoring(
+ requestingLocation,
+ mOpMonitoring,
AppOpsManager.OP_MONITOR_LOCATION);
// Now update monitoring of high power requests only.
- // A high power request is any gps request with interval under a threshold.
- boolean allowHighPower = allow;
- if (allowHighPower) {
- UpdateRecord gpsRecord = mUpdateRecords.get(LocationManager.GPS_PROVIDER);
- if (gpsRecord == null
- || gpsRecord.mRequest.getInterval() > HIGH_POWER_INTERVAL_MS) {
- allowHighPower = false;
- }
- }
boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
- mOpHighPowerMonitoring = updateMonitoring(allowHighPower, mOpHighPowerMonitoring,
+ mOpHighPowerMonitoring = updateMonitoring(
+ requestingHighPowerLocation,
+ mOpHighPowerMonitoring,
AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
- // send an intent to notify that a high power request has been added/removed.
+ // Send an intent to notify that a high power request has been added/removed.
Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
}
@@ -689,6 +710,10 @@ public class LocationManagerService extends ILocationManager.Stub {
}
public boolean callProviderEnabledLocked(String provider, boolean enabled) {
+ // First update AppOp monitoring.
+ // An app may get/lose location access as providers are enabled/disabled.
+ updateMonitoring(true);
+
if (mListener != null) {
try {
synchronized (this) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index a6d7e3c..8f4b6c2 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -21,12 +21,12 @@ import static com.android.internal.util.XmlUtils.readIntAttribute;
import static com.android.internal.util.XmlUtils.writeIntAttribute;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
-
import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
import android.app.AppOpsManager;
import android.appwidget.AppWidgetManager;
import android.util.ArrayMap;
+
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsService;
@@ -52,6 +52,7 @@ import com.android.server.pm.UserManagerService;
import com.android.server.wm.AppTransition;
import com.android.server.wm.StackBox;
import com.android.server.wm.WindowManagerService;
+
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
@@ -154,6 +155,7 @@ import android.os.UpdateLock;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.format.Time;
+import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.EventLog;
import android.util.Log;
@@ -536,7 +538,7 @@ public final class ActivityManagerService extends ActivityManagerNative
* This is the process holding what we currently consider to be
* the "home" activity.
*/
- ProcessRecord mHomeProcess;
+ ArraySet<ProcessRecord> mHomeProcess = new ArraySet<ProcessRecord>();
/**
* This is the process holding the activity the user last visited that
@@ -8062,12 +8064,10 @@ public final class ActivityManagerService extends ActivityManagerNative
if (activity == null) {
Slog.w(TAG, "getAssistContextExtras error: no resumed activity");
validActivity = false;
- }
- if (activity.app == null || activity.app.thread == null) {
+ } else if (activity.app == null || activity.app.thread == null) {
Slog.w(TAG, "getAssistContextExtras error: no process for " + activity);
validActivity = false;
- }
- if (activity.app.pid == Binder.getCallingPid()) {
+ } else if (activity.app.pid == Binder.getCallingPid()) {
Slog.w(TAG, "getAssistContextExtras error: request process same as " + activity);
validActivity = false;
}
@@ -8154,18 +8154,20 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
- public void convertFromTranslucent(IBinder token) {
+ public boolean convertFromTranslucent(IBinder token) {
final long origId = Binder.clearCallingIdentity();
try {
synchronized (this) {
final ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r == null) {
- return;
+ return false;
}
if (r.changeWindowTranslucency(true)) {
mWindowManager.setAppFullscreen(token, true);
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
+ return true;
}
+ return false;
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -8173,19 +8175,21 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
- public void convertToTranslucent(IBinder token) {
+ public boolean convertToTranslucent(IBinder token) {
final long origId = Binder.clearCallingIdentity();
try {
synchronized (this) {
final ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r == null) {
- return;
+ return false;
}
if (r.changeWindowTranslucency(false)) {
r.task.stack.convertToTranslucent(r);
mWindowManager.setAppFullscreen(token, false);
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
+ return true;
}
+ return false;
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -8953,11 +8957,11 @@ public final class ActivityManagerService extends ActivityManagerNative
// replaced by a third-party app, clear the package preferred activities from packages
// with a home activity running in the process to prevent a repeatedly crashing app
// from blocking the user to manually clear the list.
- if (app == mHomeProcess && mHomeProcess.activities.size() > 0
- && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
- Iterator<ActivityRecord> it = mHomeProcess.activities.iterator();
- while (it.hasNext()) {
- ActivityRecord r = it.next();
+ final ArrayList<ActivityRecord> activities = app.activities;
+ if (mHomeProcess.contains(app) && activities.size() > 0
+ && (app.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+ for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
+ final ActivityRecord r = activities.get(activityNdx);
if (r.isHomeActivity()) {
Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
try {
@@ -10232,13 +10236,20 @@ public final class ActivityManagerService extends ActivityManagerNative
pw.print(" mStartedUserArray: "); pw.println(Arrays.toString(mStartedUserArray));
}
}
- if (mHomeProcess != null && (dumpPackage == null
- || mHomeProcess.pkgList.containsKey(dumpPackage))) {
- if (needSep) {
- pw.println();
- needSep = false;
+ if (!mHomeProcess.isEmpty()) {
+ final int size = mHomeProcess.size();
+ ProcessRecord[] processes = new ProcessRecord[size];
+ mHomeProcess.toArray(processes);
+ for (int processNdx = 0; processNdx < size; ++processNdx) {
+ final ProcessRecord app = processes[processNdx];
+ if (dumpPackage == null || app.pkgList.containsKey(dumpPackage)) {
+ if (needSep) {
+ pw.println();
+ needSep = false;
+ }
+ pw.println(" mHomeProcess[" + processNdx + "]: " + app);
+ }
}
- pw.println(" mHomeProcess: " + mHomeProcess);
}
if (mPreviousProcess != null && (dumpPackage == null
|| mPreviousProcess.pkgList.containsKey(dumpPackage))) {
@@ -11739,10 +11750,10 @@ public final class ActivityManagerService extends ActivityManagerNative
}
return inLaunching;
}
-
+
/**
* Main code for cleaning up a process when it has gone away. This is
- * called both as a result of the process dying, or directly when stopping
+ * called both as a result of the process dying, or directly when stopping
* a process when running in single process mode.
*/
private final void cleanUpApplicationRecordLocked(ProcessRecord app,
@@ -11753,7 +11764,7 @@ public final class ActivityManagerService extends ActivityManagerNative
mProcessesToGc.remove(app);
mPendingPssProcesses.remove(app);
-
+
// Dismiss any open dialogs.
if (app.crashDialog != null && !app.forceCrashReport) {
app.crashDialog.dismiss();
@@ -11770,7 +11781,7 @@ public final class ActivityManagerService extends ActivityManagerNative
app.crashing = false;
app.notResponding = false;
-
+
app.resetPackageList(mProcessStats);
app.unlinkDeathRecipient();
app.thread = null;
@@ -11803,7 +11814,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (checkAppInLaunchingProvidersLocked(app, false)) {
restart = true;
}
-
+
// Unregister from connected content providers.
if (!app.conProviders.isEmpty()) {
for (int i=0; i<app.conProviders.size(); i++) {
@@ -11830,7 +11841,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
}
-
+
skipCurrentReceiverLocked(app);
// Unregister any receivers.
@@ -11861,6 +11872,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, null).sendToTarget();
+ mHomeProcess.remove(app);
+
// If the caller is restarting this app, then leave it in its
// current lists and let the caller take care of it.
if (restarting) {
@@ -11890,8 +11903,8 @@ public final class ActivityManagerService extends ActivityManagerNative
"Clean-up removing on hold: " + app);
mProcessesOnHold.remove(app);
- if (app == mHomeProcess) {
- mHomeProcess = null;
+ if (mHomeProcess.contains(app)) {
+ mHomeProcess.remove(app);
}
if (app == mPreviousProcess) {
mPreviousProcess = null;
@@ -13817,7 +13830,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- if (app == mHomeProcess) {
+ if (mHomeProcess.contains(app)) {
if (adj > ProcessList.HOME_APP_ADJ) {
// This process is hosting what we currently consider to be the
// home app, so we don't want to let it go into the background.
@@ -13884,7 +13897,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (procState > ActivityManager.PROCESS_STATE_SERVICE) {
procState = ActivityManager.PROCESS_STATE_SERVICE;
}
- if (app.hasShownUi && app != mHomeProcess) {
+ if (app.hasShownUi && !mHomeProcess.contains(app)) {
// If this process has shown some UI, let it immediately
// go to the LRU list because it may be pretty heavy with
// UI stuff. We'll tag it with a label just to help
@@ -13947,7 +13960,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
// Not doing bind OOM management, so treat
// this guy more like a started service.
- if (app.hasShownUi && app != mHomeProcess) {
+ if (app.hasShownUi && !mHomeProcess.contains(app)) {
// If this process has shown some UI, let it immediately
// go to the LRU list because it may be pretty heavy with
// UI stuff. We'll tag it with a label just to help
@@ -14002,7 +14015,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// about letting this process get into the LRU
// list to be killed and restarted if needed for
// memory.
- if (app.hasShownUi && app != mHomeProcess
+ if (app.hasShownUi && !mHomeProcess.contains(app)
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adjType = "cch-bound-ui-services";
} else {
@@ -14116,7 +14129,7 @@ public final class ActivityManagerService extends ActivityManagerNative
clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
}
if (adj > clientAdj) {
- if (app.hasShownUi && app != mHomeProcess
+ if (app.hasShownUi && !mHomeProcess.contains(app)
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
app.adjType = "cch-ui-provider";
} else {
@@ -14976,7 +14989,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// to be good enough at this point that destroying
// activities causes more harm than good.
if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
- && app != mHomeProcess && app != mPreviousProcess) {
+ && !mHomeProcess.contains(app) && app != mPreviousProcess) {
// Need to do this on its own message because the stack may not
// be in a consistent state at this point.
// For these apps we will also finish their activities
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index a0bbfad..2fefadf 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -2246,7 +2246,7 @@ final class ActivityStack {
if (r.state == ActivityState.RESUMED
|| r.state == ActivityState.PAUSING
|| r.state == ActivityState.PAUSED) {
- if (!r.isHomeActivity() || mService.mHomeProcess != r.app) {
+ if (!r.isHomeActivity() || !mService.mHomeProcess.contains(r.app)) {
Slog.w(TAG, " Force finishing activity "
+ r.intent.getComponent().flattenToShortString());
finishActivityLocked(r, Activity.RESULT_CANCELED, null, "crashed", false);
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index 0808861..250ab4a 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -905,7 +905,7 @@ public final class ActivityStackSupervisor {
r.task.taskId, r.shortComponentName);
}
if (r.isHomeActivity() && r.isNotResolverActivity()) {
- mService.mHomeProcess = app;
+ mService.mHomeProcess.add(app);
}
mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
r.sleeping = false;
@@ -1946,7 +1946,7 @@ public final class ActivityStackSupervisor {
// makes sense to.
if (r.app != null && fgApp != null && r.app != fgApp
&& r.lastVisibleTime > mService.mPreviousProcessVisibleTime
- && r.app != mService.mHomeProcess) {
+ && !mService.mHomeProcess.contains(r.app)) {
mService.mPreviousProcess = r.app;
mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
}
diff --git a/services/java/com/android/server/connectivity/PacManager.java b/services/java/com/android/server/connectivity/PacManager.java
index defe9f0..0b68ff5 100644
--- a/services/java/com/android/server/connectivity/PacManager.java
+++ b/services/java/com/android/server/connectivity/PacManager.java
@@ -1,14 +1,31 @@
+/**
+ * Copyright (c) 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.android.server.connectivity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.net.ConnectivityManager;
+import android.content.ServiceConnection;
import android.net.ProxyProperties;
+import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -17,42 +34,26 @@ import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
import com.android.net.IProxyService;
+import com.android.server.IoThread;
+import libcore.io.Streams;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpException;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.conn.params.ConnRouteParams;
-import org.apache.http.conn.routing.HttpRoute;
-import org.apache.http.conn.routing.HttpRoutePlanner;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.protocol.HttpContext;
-
-import java.io.BufferedReader;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.InetAddress;
-import java.net.ProxySelector;
import java.net.URL;
import java.net.URLConnection;
/**
* @hide
*/
-public class PacManager implements Runnable {
- public static final int NO_ERROR = 0;
- public static final int PERMISSION_DENIED = 1;
- public static final String PROXY_SERVICE = "com.android.net.IProxyService";
+public class PacManager {
+ public static final String PROXY_PACKAGE = "com.android.pacprocessor";
+ public static final String PROXY_SERVICE = "com.android.pacprocessor.PacService";
+ public static final String PROXY_SERVICE_NAME = "com.android.net.IProxyService";
- private static final String TAG = "PACManager";
+ private static final String TAG = "PacManager";
private static final String ACTION_PAC_REFRESH = "android.net.proxy.PAC_REFRESH";
@@ -64,31 +65,57 @@ public class PacManager implements Runnable {
/** Keep these values up-to-date with ProxyService.java */
public static final String KEY_PROXY = "keyProxy";
private String mCurrentPac;
- private volatile String mPacUrl;
+ @GuardedBy("mProxyLock")
+ private String mPacUrl;
private AlarmManager mAlarmManager;
+ @GuardedBy("mProxyLock")
private IProxyService mProxyService;
private PendingIntent mPacRefreshIntent;
+ private ServiceConnection mConnection;
private Context mContext;
private int mCurrentDelay;
+ /**
+ * Used for locking when setting mProxyService and all references to mPacUrl or mCurrentPac.
+ */
+ private final Object mProxyLock = new Object();
+
+ private Runnable mPacDownloader = new Runnable() {
+ @Override
+ public void run() {
+ String file;
+ synchronized (mProxyLock) {
+ if (mPacUrl == null) return;
+ try {
+ file = get(mPacUrl);
+ } catch (IOException ioe) {
+ file = null;
+ Log.w(TAG, "Failed to load PAC file: " + ioe);
+ }
+ }
+ if (file != null) {
+ synchronized (mProxyLock) {
+ if (!file.equals(mCurrentPac)) {
+ setCurrentProxyScript(file);
+ }
+ }
+ longSchedule();
+ } else {
+ reschedule();
+ }
+ }
+ };
+
class PacRefreshIntentReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
- new Thread(PacManager.this).start();
+ IoThread.getHandler().post(mPacDownloader);
}
}
public PacManager(Context context) {
mContext = context;
- mProxyService = IProxyService.Stub.asInterface(
- ServiceManager.getService(PROXY_SERVICE));
- if (mProxyService == null) {
- // Added because of b10267814 where mako is restarting.
- Log.e(TAG, "PacManager: no proxy service");
- } else {
- Log.d(TAG, "PacManager: mProxyService available");
- }
mPacRefreshIntent = PendingIntent.getBroadcast(
context, 0, new Intent(ACTION_PAC_REFRESH), 0);
@@ -103,26 +130,28 @@ public class PacManager implements Runnable {
return mAlarmManager;
}
- public void setCurrentProxyScriptUrl(ProxyProperties proxy) {
- if (mProxyService == null) {
- Log.e(TAG, "setCurrentProxyScriptUrl: no proxy service");
- return;
- }
+ public synchronized void setCurrentProxyScriptUrl(ProxyProperties proxy) {
if (!TextUtils.isEmpty(proxy.getPacFileUrl())) {
- try {
- mProxyService.startPacSystem();
+ synchronized (mProxyLock) {
mPacUrl = proxy.getPacFileUrl();
- mCurrentDelay = DELAY_1;
- getAlarmManager().cancel(mPacRefreshIntent);
- new Thread(this).start();
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to reach ProxyService - PAC will not be started", e);
}
+ mCurrentDelay = DELAY_1;
+ getAlarmManager().cancel(mPacRefreshIntent);
+ bind();
} else {
- try {
- mProxyService.stopPacSystem();
- } catch (RemoteException e) {
- e.printStackTrace();
+ getAlarmManager().cancel(mPacRefreshIntent);
+ synchronized (mProxyLock) {
+ mPacUrl = null;
+ mCurrentPac = null;
+ if (mProxyService != null) {
+ try {
+ mProxyService.stopPacSystem();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to stop PAC service", e);
+ } finally {
+ unbind();
+ }
+ }
}
}
}
@@ -132,51 +161,10 @@ public class PacManager implements Runnable {
*
* @throws IOException
*/
- public static String get(String urlString) throws IOException {
+ private static String get(String urlString) throws IOException {
URL url = new URL(urlString);
URLConnection urlConnection = url.openConnection(java.net.Proxy.NO_PROXY);
- BufferedReader in = new BufferedReader(new InputStreamReader(
- urlConnection.getInputStream()));
- String inputLine;
- String resp = "";
- while ((inputLine = in.readLine()) != null) {
- resp = resp + inputLine + "\n";
- }
- in.close();
- return resp;
- }
-
- private static String toString(InputStream content) throws IOException {
- StringBuffer buffer = new StringBuffer();
- String line;
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(content));
-
- while ((line = bufferedReader.readLine()) != null) {
- if (buffer.length() != 0) {
- buffer.append('\n');
- }
- buffer.append(line);
- }
-
- return buffer.toString();
- }
-
- @Override
- public void run() {
- String file;
- try {
- file = get(mPacUrl);
- } catch (IOException ioe) {
- file = null;
- }
- if (file != null) {
- if (!file.equals(mCurrentPac)) {
- setCurrentProxyScript(file);
- }
- longSchedule();
- } else {
- reschedule();
- }
+ return new String(Streams.readFully(urlConnection.getInputStream()));
}
private int getNextDelay(int currentDelay) {
@@ -227,14 +215,60 @@ public class PacManager implements Runnable {
return false;
}
try {
- if (mProxyService.setPacFile(script) != NO_ERROR) {
- Log.e(TAG, "Unable to parse proxy script.");
- return false;
- }
+ mProxyService.setPacFile(script);
mCurrentPac = script;
} catch (RemoteException e) {
Log.e(TAG, "Unable to set PAC file", e);
}
return true;
}
+
+ private void bind() {
+ if (mContext == null) {
+ Log.e(TAG, "No context for binding");
+ return;
+ }
+ Intent intent = new Intent();
+ intent.setClassName(PROXY_PACKAGE, PROXY_SERVICE);
+ mConnection = new ServiceConnection() {
+ @Override
+ public void onServiceDisconnected(ComponentName component) {
+ synchronized (mProxyLock) {
+ mProxyService = null;
+ }
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName component, IBinder binder) {
+ synchronized (mProxyLock) {
+ try {
+ Log.d(TAG, "Adding service " + PROXY_SERVICE_NAME + " "
+ + binder.getInterfaceDescriptor());
+ } catch (RemoteException e1) {
+ Log.e(TAG, "Remote Exception", e1);
+ }
+ ServiceManager.addService(PROXY_SERVICE_NAME, binder);
+ mProxyService = IProxyService.Stub.asInterface(binder);
+ if (mProxyService == null) {
+ Log.e(TAG, "No proxy service");
+ } else {
+ try {
+ mProxyService.startPacSystem();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to reach ProxyService - PAC will not be started", e);
+ }
+ IoThread.getHandler().post(mPacDownloader);
+ }
+ }
+ }
+ };
+ Log.e(TAG, "Attempting to bind");
+ mContext.bindService(intent, mConnection,
+ Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE);
+ }
+
+ private void unbind() {
+ mContext.unbindService(mConnection);
+ mConnection = null;
+ }
}
diff --git a/services/java/com/android/server/content/SyncManager.java b/services/java/com/android/server/content/SyncManager.java
index ee5b890..a6b69a2 100644
--- a/services/java/com/android/server/content/SyncManager.java
+++ b/services/java/com/android/server/content/SyncManager.java
@@ -2889,11 +2889,12 @@ public class SyncManager {
// determine if we need to set or cancel the alarm
boolean shouldSet = false;
boolean shouldCancel = false;
- final boolean alarmIsActive = mAlarmScheduleTime != null;
+ final boolean alarmIsActive = (mAlarmScheduleTime != null) && (now < mAlarmScheduleTime);
final boolean needAlarm = alarmTime != Long.MAX_VALUE;
if (needAlarm) {
- // Need the alarm if it's currently not set, or if our time is before the currently
- // set time.
+ // Need the alarm if
+ // - it's currently not set
+ // - if the alarm is set in the past.
if (!alarmIsActive || alarmTime < mAlarmScheduleTime) {
shouldSet = true;
}
@@ -2910,7 +2911,7 @@ public class SyncManager {
+ " secs from now");
}
mAlarmScheduleTime = alarmTime;
- mAlarmService.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime,
+ mAlarmService.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime,
mSyncAlarmIntent);
} else if (shouldCancel) {
mAlarmScheduleTime = null;
diff --git a/services/java/com/android/server/content/SyncStorageEngine.java b/services/java/com/android/server/content/SyncStorageEngine.java
index 25529a6..e3693f8 100644
--- a/services/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/java/com/android/server/content/SyncStorageEngine.java
@@ -53,6 +53,7 @@ import org.xmlpull.v1.XmlSerializer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
@@ -71,7 +72,7 @@ public class SyncStorageEngine extends Handler {
private static final String TAG = "SyncManager";
private static final boolean DEBUG = true;
- private static final boolean DEBUG_FILE = true;
+ private static final String TAG_FILE = "SyncManagerFile";
private static final String XML_ATTR_NEXT_AUTHORITY_ID = "nextAuthorityId";
private static final String XML_ATTR_LISTEN_FOR_TICKLES = "listen-for-tickles";
@@ -420,9 +421,12 @@ public class SyncStorageEngine extends Handler {
File systemDir = new File(dataDir, "system");
File syncDir = new File(systemDir, "sync");
syncDir.mkdirs();
+
+ maybeDeleteLegacyPendingInfoLocked(syncDir);
+
mAccountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
mStatusFile = new AtomicFile(new File(syncDir, "status.bin"));
- mPendingFile = new AtomicFile(new File(syncDir, "pending.bin"));
+ mPendingFile = new AtomicFile(new File(syncDir, "pending.xml"));
mStatisticsFile = new AtomicFile(new File(syncDir, "stats.bin"));
readAccountInfoLocked();
@@ -676,7 +680,8 @@ public class SyncStorageEngine extends Handler {
continue;
}
for (AuthorityInfo authorityInfo : accountInfo.authorities.values()) {
- if (providerName != null && !providerName.equals(authorityInfo.authority)) {
+ if (providerName != null
+ && !providerName.equals(authorityInfo.authority)) {
continue;
}
if (authorityInfo.backoffTime != nextSyncTime
@@ -774,10 +779,12 @@ public class SyncStorageEngine extends Handler {
}
synchronized (mAuthorities) {
if (toUpdate.period <= 0 && add) {
- Log.e(TAG, "period < 0, should never happen in updateOrRemovePeriodicSync: add-" + add);
+ Log.e(TAG, "period < 0, should never happen in updateOrRemovePeriodicSync: add-"
+ + add);
}
if (toUpdate.extras == null) {
- Log.e(TAG, "period < 0, should never happen in updateOrRemovePeriodicSync: add-" + add);
+ Log.e(TAG, "null extras, should never happen in updateOrRemovePeriodicSync: add-"
+ + add);
}
try {
AuthorityInfo authority =
@@ -806,7 +813,7 @@ public class SyncStorageEngine extends Handler {
if (!alreadyPresent) {
authority.periodicSyncs.add(new PeriodicSync(toUpdate));
SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
- status.setPeriodicSyncTime(authority.periodicSyncs.size() - 1, 0);
+ status.setPeriodicSyncTime(authority.periodicSyncs.size() - 1, 0L);
}
} else {
// Remove any periodic syncs that match the authority and extras.
@@ -824,7 +831,8 @@ public class SyncStorageEngine extends Handler {
if (status != null) {
status.removePeriodicSyncTime(i);
} else {
- Log.e(TAG, "Tried removing sync status on remove periodic sync but did not find it.");
+ Log.e(TAG, "Tried removing sync status on remove periodic sync but"
+ + "did not find it.");
}
} else {
i++;
@@ -942,7 +950,7 @@ public class SyncStorageEngine extends Handler {
op = new PendingOperation(op);
op.authorityId = authority.ident;
mPendingOperations.add(op);
- writePendingOperationsLocked();
+ appendPendingOperationLocked(op);
SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
status.pending = true;
@@ -1660,7 +1668,9 @@ public class SyncStorageEngine extends Handler {
FileInputStream fis = null;
try {
fis = mAccountInfoFile.openRead();
- if (DEBUG_FILE) Log.v(TAG, "Reading " + mAccountInfoFile.getBaseFile());
+ if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+ Log.v(TAG, "Reading " + mAccountInfoFile.getBaseFile());
+ }
XmlPullParser parser = Xml.newPullParser();
parser.setInput(fis, null);
int eventType = parser.getEventType();
@@ -1745,6 +1755,20 @@ public class SyncStorageEngine extends Handler {
}
/**
+ * Ensure the old pending.bin is deleted, as it has been changed to pending.xml.
+ * pending.xml was used starting in KLP.
+ * @param syncDir directory where the sync files are located.
+ */
+ private void maybeDeleteLegacyPendingInfoLocked(File syncDir) {
+ File file = new File(syncDir, "pending.bin");
+ if (!file.exists()) {
+ return;
+ } else {
+ file.delete();
+ }
+ }
+
+ /**
* some authority names have changed. copy over their settings and delete the old ones
* @return true if a change was made
*/
@@ -1832,18 +1856,21 @@ public class SyncStorageEngine extends Handler {
syncable = "unknown";
}
authority = mAuthorities.get(id);
- if (DEBUG_FILE) Log.v(TAG, "Adding authority: account="
- + accountName + " auth=" + authorityName
- + " user=" + userId
- + " enabled=" + enabled
- + " syncable=" + syncable);
+ if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+ Log.v(TAG, "Adding authority: account="
+ + accountName + " auth=" + authorityName
+ + " user=" + userId
+ + " enabled=" + enabled
+ + " syncable=" + syncable);
+ }
if (authority == null) {
- if (DEBUG_FILE) {
+ if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
Log.v(TAG, "Creating entry");
}
if (accountName != null && accountType != null) {
authority = getOrCreateAuthorityLocked(
- new Account(accountName, accountType), userId, authorityName, id, false);
+ new Account(accountName, accountType), userId, authorityName, id,
+ false);
} else {
authority = getOrCreateAuthorityLocked(
new ComponentName(packageName, className), userId, id, false);
@@ -1943,7 +1970,9 @@ public class SyncStorageEngine extends Handler {
* Write all account information to the account file.
*/
private void writeAccountInfoLocked() {
- if (DEBUG_FILE) Log.v(TAG, "Writing new " + mAccountInfoFile.getBaseFile());
+ if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+ Log.v(TAG, "Writing new " + mAccountInfoFile.getBaseFile());
+ }
FileOutputStream fos = null;
try {
@@ -2041,7 +2070,9 @@ public class SyncStorageEngine extends Handler {
final boolean hasType = db.getVersion() >= 11;
// Copy in all of the status information, as well as accounts.
- if (DEBUG_FILE) Log.v(TAG, "Reading legacy sync accounts db");
+ if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+ Log.v(TAG, "Reading legacy sync accounts db");
+ }
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables("stats, status");
HashMap<String,String> map = new HashMap<String,String>();
@@ -2151,7 +2182,9 @@ public class SyncStorageEngine extends Handler {
* Read all sync status back in to the initial engine state.
*/
private void readStatusLocked() {
- if (DEBUG_FILE) Log.v(TAG, "Reading " + mStatusFile.getBaseFile());
+ if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+ Log.v(TAG, "Reading " + mStatusFile.getBaseFile());
+ }
try {
byte[] data = mStatusFile.readFully();
Parcel in = Parcel.obtain();
@@ -2163,8 +2196,10 @@ public class SyncStorageEngine extends Handler {
SyncStatusInfo status = new SyncStatusInfo(in);
if (mAuthorities.indexOfKey(status.authorityId) >= 0) {
status.pending = false;
- if (DEBUG_FILE) Log.v(TAG, "Adding status for id "
- + status.authorityId);
+ if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+ Log.v(TAG, "Adding status for id "
+ + status.authorityId);
+ }
mSyncStatus.put(status.authorityId, status);
}
} else {
@@ -2182,7 +2217,9 @@ public class SyncStorageEngine extends Handler {
* Write all sync status to the sync status file.
*/
private void writeStatusLocked() {
- if (DEBUG_FILE) Log.v(TAG, "Writing new " + mStatusFile.getBaseFile());
+ if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+ Log.v(TAG, "Writing new " + mStatusFile.getBaseFile());
+ }
// The file is being written, so we don't need to have a scheduled
// write until the next change.
@@ -2211,103 +2248,97 @@ public class SyncStorageEngine extends Handler {
}
}
- public static final int PENDING_OPERATION_VERSION = 4;
+ public static final int PENDING_OPERATION_VERSION = 3;
- /**
- * Read all pending operations back in to the initial engine state.
- */
+ /** Read all pending operations back in to the initial engine state. */
private void readPendingOperationsLocked() {
- if (DEBUG_FILE) Log.v(TAG, "Reading " + mPendingFile.getBaseFile());
- try {
- readPendingAsXml();
- } catch (XmlPullParserException e) {
- Log.d(TAG, "Error parsing pending as xml, trying as parcel.");
- try {
- readPendingAsParcelled();
- } catch (java.io.IOException e1) {
- Log.i(TAG, "No initial pending operations");
+ FileInputStream fis = null;
+ if (!mPendingFile.getBaseFile().exists()) {
+ if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+ Log.v(TAG_FILE, "No pending operation file.");
+ return;
}
}
- }
-
- private void readPendingAsXml() throws XmlPullParserException {
- FileInputStream fis = null;
try {
fis = mPendingFile.openRead();
- XmlPullParser parser = Xml.newPullParser();
+ XmlPullParser parser;
+ parser = Xml.newPullParser();
parser.setInput(fis, null);
+
int eventType = parser.getEventType();
while (eventType != XmlPullParser.START_TAG &&
eventType != XmlPullParser.END_DOCUMENT) {
eventType = parser.next();
}
- if (eventType == XmlPullParser.END_DOCUMENT) return;
+ if (eventType == XmlPullParser.END_DOCUMENT) return; // Nothing to read.
String tagName = parser.getName();
- if ("pending".equals(tagName)) {
- int version = -1;
- String versionString = parser.getAttributeValue(null, "version");
- if (versionString == null ||
- Integer.parseInt(versionString) != PENDING_OPERATION_VERSION) {
- Log.w(TAG, "Unknown pending operation version "
- + version + "; trying to read as binary.");
- throw new XmlPullParserException("Unknown version.");
- }
- eventType = parser.next();
+ do {
PendingOperation pop = null;
- do {
- if (eventType == XmlPullParser.START_TAG) {
- try {
- tagName = parser.getName();
- if (parser.getDepth() == 2 && "op".equals(tagName)) {
- int authorityId = Integer.valueOf(parser.getAttributeValue(
- null, XML_ATTR_AUTHORITYID));
- boolean expedited = Boolean.valueOf(parser.getAttributeValue(
- null, XML_ATTR_EXPEDITED));
- int syncSource = Integer.valueOf(parser.getAttributeValue(
- null, XML_ATTR_SOURCE));
- int reason = Integer.valueOf(parser.getAttributeValue(
- null, XML_ATTR_REASON));
- AuthorityInfo authority = mAuthorities.get(authorityId);
- if (DEBUG_FILE) {
- Log.v(TAG, authorityId + " " + expedited + " " + syncSource + " " + reason);
- }
- if (authority != null) {
- pop = new PendingOperation(
- authority.account, authority.userId, reason, syncSource,
- authority.authority, new Bundle(), expedited);
- pop.authorityId = authorityId;
- pop.flatExtras = null; // No longer used.
- mPendingOperations.add(pop);
- if (DEBUG_FILE) Log.v(TAG, "Adding pending op: account=" + pop.account
- + " auth=" + pop.authority
+ if (eventType == XmlPullParser.START_TAG) {
+ try {
+ tagName = parser.getName();
+ if (parser.getDepth() == 1 && "op".equals(tagName)) {
+ // Verify version.
+ String versionString =
+ parser.getAttributeValue(null, XML_ATTR_VERSION);
+ if (versionString == null ||
+ Integer.parseInt(versionString) != PENDING_OPERATION_VERSION) {
+ Log.w(TAG, "Unknown pending operation version " + versionString);
+ throw new java.io.IOException("Unknown version.");
+ }
+ int authorityId = Integer.valueOf(parser.getAttributeValue(
+ null, XML_ATTR_AUTHORITYID));
+ boolean expedited = Boolean.valueOf(parser.getAttributeValue(
+ null, XML_ATTR_EXPEDITED));
+ int syncSource = Integer.valueOf(parser.getAttributeValue(
+ null, XML_ATTR_SOURCE));
+ int reason = Integer.valueOf(parser.getAttributeValue(
+ null, XML_ATTR_REASON));
+ AuthorityInfo authority = mAuthorities.get(authorityId);
+ if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+ Log.v(TAG_FILE, authorityId + " " + expedited + " " + syncSource + " "
+ + reason);
+ }
+ if (authority != null) {
+ pop = new PendingOperation(
+ authority.account, authority.userId, reason,
+ syncSource, authority.authority, new Bundle(),
+ expedited);
+ pop.flatExtras = null; // No longer used.
+ mPendingOperations.add(pop);
+ if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+ Log.v(TAG_FILE, "Adding pending op: "
+ + pop.authority
+ " src=" + pop.syncSource
+ " reason=" + pop.reason
+ " expedited=" + pop.expedited);
- } else {
- // Skip non-existent authority;
- pop = null;
- if (DEBUG_FILE) {
- Log.v(TAG, "No authority found for " + authorityId
- + ", skipping");
- }
}
- } else if (parser.getDepth() == 3 &&
- pop != null &&
- "extra".equals(tagName)) {
- parseExtra(parser, pop.extras);
+ } else {
+ // Skip non-existent authority.
+ pop = null;
+ if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+ Log.v(TAG_FILE, "No authority found for " + authorityId
+ + ", skipping");
+ }
}
- } catch (NumberFormatException e) {
- Log.d(TAG, "Invalid data in xml file.", e);
+ } else if (parser.getDepth() == 2 &&
+ pop != null &&
+ "extra".equals(tagName)) {
+ parseExtra(parser, pop.extras);
}
+ } catch (NumberFormatException e) {
+ Log.d(TAG, "Invalid data in xml file.", e);
}
- eventType = parser.next();
- } while(eventType != XmlPullParser.END_DOCUMENT);
- }
+ }
+ eventType = parser.next();
+ } while(eventType != XmlPullParser.END_DOCUMENT);
} catch (java.io.IOException e) {
- if (fis == null) Log.i(TAG, "No initial pending operations.");
- else Log.w(TAG, "Error reading pending data.", e);
- return;
+ Log.w(TAG_FILE, "Error reading pending data.", e);
+ } catch (XmlPullParserException e) {
+ if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+ Log.w(TAG_FILE, "Error parsing pending ops xml.", e);
+ }
} finally {
if (fis != null) {
try {
@@ -2316,60 +2347,99 @@ public class SyncStorageEngine extends Handler {
}
}
}
+
+ private static final String XML_ATTR_AUTHORITYID = "authority_id";
+ private static final String XML_ATTR_SOURCE = "source";
+ private static final String XML_ATTR_EXPEDITED = "expedited";
+ private static final String XML_ATTR_REASON = "reason";
+ private static final String XML_ATTR_VERSION = "version";
+
/**
- * Old format of reading pending.bin as a parcelled file. Replaced in lieu of JSON because
- * persisting parcels is unsafe.
- * @throws java.io.IOException
+ * Write all currently pending ops to the pending ops file.
*/
- private void readPendingAsParcelled() throws java.io.IOException {
- byte[] data = mPendingFile.readFully();
- Parcel in = Parcel.obtain();
- in.unmarshall(data, 0, data.length);
- in.setDataPosition(0);
- final int SIZE = in.dataSize();
- while (in.dataPosition() < SIZE) {
- int version = in.readInt();
- if (version != 3 && version != 1) {
- Log.w(TAG, "Unknown pending operation version "
- + version + "; dropping all ops");
- break;
- }
- int authorityId = in.readInt();
- int syncSource = in.readInt();
- byte[] flatExtras = in.createByteArray();
- boolean expedited;
- if (version == PENDING_OPERATION_VERSION) {
- expedited = in.readInt() != 0;
- } else {
- expedited = false;
- }
- int reason = in.readInt();
- AuthorityInfo authority = mAuthorities.get(authorityId);
- if (authority != null) {
- Bundle extras;
- if (flatExtras != null) {
- extras = unflattenBundle(flatExtras);
- } else {
- // if we are unable to parse the extras for whatever reason convert this
- // to a regular sync by creating an empty extras
- extras = new Bundle();
+ private void writePendingOperationsLocked() {
+ final int N = mPendingOperations.size();
+ FileOutputStream fos = null;
+ try {
+ if (N == 0) {
+ if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+ Log.v(TAG_FILE, "Truncating " + mPendingFile.getBaseFile());
}
- PendingOperation op = new PendingOperation(
- authority.account, authority.userId, reason, syncSource,
- authority.authority, extras, expedited);
- op.authorityId = authorityId;
- op.flatExtras = flatExtras;
- if (DEBUG_FILE) Log.v(TAG, "Adding pending op: account=" + op.account
- + " auth=" + op.authority
- + " src=" + op.syncSource
- + " reason=" + op.reason
- + " expedited=" + op.expedited
- + " extras=" + op.extras);
- mPendingOperations.add(op);
+ mPendingFile.truncate();
+ return;
+ }
+ if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+ Log.v(TAG_FILE, "Writing new " + mPendingFile.getBaseFile());
+ }
+ fos = mPendingFile.startWrite();
+ XmlSerializer out = new FastXmlSerializer();
+ out.setOutput(fos, "utf-8");
+
+ for (int i = 0; i < N; i++) {
+ PendingOperation pop = mPendingOperations.get(i);
+ writePendingOperationLocked(pop, out);
+ }
+ out.endDocument();
+ mPendingFile.finishWrite(fos);
+ } catch (java.io.IOException e1) {
+ Log.w(TAG, "Error writing pending operations", e1);
+ if (fos != null) {
+ mPendingFile.failWrite(fos);
}
}
}
+ /** Write all currently pending ops to the pending ops file. */
+ private void writePendingOperationLocked(PendingOperation pop, XmlSerializer out)
+ throws IOException {
+ // Pending operation.
+ out.startTag(null, "op");
+
+ out.attribute(null, XML_ATTR_VERSION, Integer.toString(PENDING_OPERATION_VERSION));
+ out.attribute(null, XML_ATTR_AUTHORITYID, Integer.toString(pop.authorityId));
+ out.attribute(null, XML_ATTR_SOURCE, Integer.toString(pop.syncSource));
+ out.attribute(null, XML_ATTR_EXPEDITED, Boolean.toString(pop.expedited));
+ out.attribute(null, XML_ATTR_REASON, Integer.toString(pop.reason));
+ extrasToXml(out, pop.extras);
+
+ out.endTag(null, "op");
+ }
+
+ /**
+ * Append the given operation to the pending ops file; if unable to,
+ * write all pending ops.
+ */
+ private void appendPendingOperationLocked(PendingOperation op) {
+ if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+ Log.v(TAG, "Appending to " + mPendingFile.getBaseFile());
+ }
+ FileOutputStream fos = null;
+ try {
+ fos = mPendingFile.openAppend();
+ } catch (java.io.IOException e) {
+ if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+ Log.v(TAG, "Failed append; writing full file");
+ }
+ writePendingOperationsLocked();
+ return;
+ }
+
+ try {
+ XmlSerializer out = new FastXmlSerializer();
+ out.setOutput(fos, "utf-8");
+ writePendingOperationLocked(op, out);
+ out.endDocument();
+ mPendingFile.finishWrite(fos);
+ } catch (java.io.IOException e1) {
+ Log.w(TAG, "Error writing appending operation", e1);
+ mPendingFile.failWrite(fos);
+ } finally {
+ try {
+ fos.close();
+ } catch (IOException e) {}
+ }
+ }
+
static private byte[] flattenBundle(Bundle bundle) {
byte[] flatData = null;
Parcel parcel = Parcel.obtain();
@@ -2399,54 +2469,6 @@ public class SyncStorageEngine extends Handler {
return bundle;
}
- private static final String XML_ATTR_AUTHORITYID = "authority_id";
- private static final String XML_ATTR_SOURCE = "source";
- private static final String XML_ATTR_EXPEDITED = "expedited";
- private static final String XML_ATTR_REASON = "reason";
- /**
- * Write all currently pending ops to the pending ops file. TODO: Change this from xml
- * so that we can append to this file as before.
- */
- private void writePendingOperationsLocked() {
- final int N = mPendingOperations.size();
- FileOutputStream fos = null;
- try {
- if (N == 0) {
- if (DEBUG_FILE) Log.v(TAG, "Truncating " + mPendingFile.getBaseFile());
- mPendingFile.truncate();
- return;
- }
- if (DEBUG_FILE) Log.v(TAG, "Writing new " + mPendingFile.getBaseFile());
- fos = mPendingFile.startWrite();
- XmlSerializer out = new FastXmlSerializer();
- out.setOutput(fos, "utf-8");
- out.startDocument(null, true);
- out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
-
- out.startTag(null, "pending");
- out.attribute(null, "version", Integer.toString(PENDING_OPERATION_VERSION));
-
- for (int i = 0; i < N; i++) {
- PendingOperation pop = mPendingOperations.get(i);
- out.startTag(null, "op");
- out.attribute(null, XML_ATTR_AUTHORITYID, Integer.toString(pop.authorityId));
- out.attribute(null, XML_ATTR_SOURCE, Integer.toString(pop.syncSource));
- out.attribute(null, XML_ATTR_EXPEDITED, Boolean.toString(pop.expedited));
- out.attribute(null, XML_ATTR_REASON, Integer.toString(pop.reason));
- extrasToXml(out, pop.extras);
- out.endTag(null, "op");
- }
- out.endTag(null, "pending");
- out.endDocument();
- mPendingFile.finishWrite(fos);
- } catch (java.io.IOException e1) {
- Log.w(TAG, "Error writing pending operations", e1);
- if (fos != null) {
- mPendingFile.failWrite(fos);
- }
- }
- }
-
private void extrasToXml(XmlSerializer out, Bundle extras) throws java.io.IOException {
for (String key : extras.keySet()) {
out.startTag(null, "extra");
@@ -2479,35 +2501,6 @@ public class SyncStorageEngine extends Handler {
}
}
-// /**
-// * Update the pending ops file, if e
-// */
-// private void appendPendingOperationLocked(PendingOperation op) {
-// if (DEBUG_FILE) Log.v(TAG, "Appending to " + mPendingFile.getBaseFile());
-// FileOutputStream fos = null;
-// try {
-// fos = mPendingFile.openAppend();
-// } catch (java.io.IOException e) {
-// if (DEBUG_FILE) Log.v(TAG, "Failed append; writing full file");
-// writePendingOperationsLocked();
-// return;
-// }
-//
-// try {
-// Parcel out = Parcel.obtain();
-// writePendingOperationLocked(op, out);
-// fos.write(out.marshall());
-// out.recycle();
-// } catch (java.io.IOException e1) {
-// Log.w(TAG, "Error writing pending operations", e1);
-// } finally {
-// try {
-// fos.close();
-// } catch (java.io.IOException e2) {
-// }
-// }
-// }
-
private void requestSync(Account account, int userId, int reason, String authority,
Bundle extras) {
// If this is happening in the system process, then call the syncrequest listener
@@ -2568,7 +2561,9 @@ public class SyncStorageEngine extends Handler {
* Write all sync statistics to the sync status file.
*/
private void writeStatisticsLocked() {
- if (DEBUG_FILE) Log.v(TAG, "Writing new " + mStatisticsFile.getBaseFile());
+ if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+ Log.v(TAG, "Writing new " + mStatisticsFile.getBaseFile());
+ }
// The file is being written, so we don't need to have a scheduled
// write until the next change.
@@ -2611,7 +2606,7 @@ public class SyncStorageEngine extends Handler {
sb.append("Pending Ops: ").append(mPendingOperations.size()).append(" operation(s)\n");
for (PendingOperation pop : mPendingOperations) {
sb.append("(" + pop.account)
- .append(", " + pop.userId)
+ .append(", u" + pop.userId)
.append(", " + pop.authority)
.append(", " + pop.extras)
.append(")\n");
diff --git a/services/java/com/android/server/display/WifiDisplayController.java b/services/java/com/android/server/display/WifiDisplayController.java
index f89917c..846a74d 100644
--- a/services/java/com/android/server/display/WifiDisplayController.java
+++ b/services/java/com/android/server/display/WifiDisplayController.java
@@ -83,11 +83,6 @@ final class WifiDisplayController implements DumpUtils.Dump {
private static final int CONNECT_MAX_RETRIES = 3;
private static final int CONNECT_RETRY_DELAY_MILLIS = 500;
- // A unique token to identify the remote submix that is managed by Wifi display.
- // It must match what the media server uses when it starts recording the submix
- // for transmission. We use 0 although the actual value is currently ignored.
- private static final int REMOTE_SUBMIX_ADDRESS = 0;
-
private final Context mContext;
private final Handler mHandler;
private final Listener mListener;
@@ -95,8 +90,6 @@ final class WifiDisplayController implements DumpUtils.Dump {
private final WifiP2pManager mWifiP2pManager;
private final Channel mWifiP2pChannel;
- private final AudioManager mAudioManager;
-
private boolean mWifiP2pEnabled;
private boolean mWfdEnabled;
private boolean mWfdEnabling;
@@ -146,9 +139,6 @@ final class WifiDisplayController implements DumpUtils.Dump {
// True if RTSP has connected.
private boolean mRemoteDisplayConnected;
- // True if the remote submix is enabled.
- private boolean mRemoteSubmixOn;
-
// The information we have most recently told WifiDisplayAdapter about.
private WifiDisplay mAdvertisedDisplay;
private Surface mAdvertisedDisplaySurface;
@@ -164,8 +154,6 @@ final class WifiDisplayController implements DumpUtils.Dump {
mWifiP2pManager = (WifiP2pManager)context.getSystemService(Context.WIFI_P2P_SERVICE);
mWifiP2pChannel = mWifiP2pManager.initialize(context, handler.getLooper(), null);
- mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
-
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
@@ -211,7 +199,6 @@ final class WifiDisplayController implements DumpUtils.Dump {
pw.println("mRemoteDisplay=" + mRemoteDisplay);
pw.println("mRemoteDisplayInterface=" + mRemoteDisplayInterface);
pw.println("mRemoteDisplayConnected=" + mRemoteDisplayConnected);
- pw.println("mRemoteSubmixOn=" + mRemoteSubmixOn);
pw.println("mAdvertisedDisplay=" + mAdvertisedDisplay);
pw.println("mAdvertisedDisplaySurface=" + mAdvertisedDisplaySurface);
pw.println("mAdvertisedDisplayWidth=" + mAdvertisedDisplayWidth);
@@ -482,7 +469,6 @@ final class WifiDisplayController implements DumpUtils.Dump {
mHandler.removeCallbacks(mRtspTimeout);
mWifiP2pManager.setMiracastMode(WifiP2pManager.MIRACAST_DISABLED);
- setRemoteSubmixOn(false);
unadvertiseDisplay();
// continue to next step
@@ -626,7 +612,6 @@ final class WifiDisplayController implements DumpUtils.Dump {
return; // done
}
- setRemoteSubmixOn(true);
mWifiP2pManager.setMiracastMode(WifiP2pManager.MIRACAST_SOURCE);
final WifiP2pDevice oldDevice = mConnectedDevice;
@@ -677,13 +662,6 @@ final class WifiDisplayController implements DumpUtils.Dump {
}
}
- private void setRemoteSubmixOn(boolean on) {
- if (mRemoteSubmixOn != on) {
- mRemoteSubmixOn = on;
- mAudioManager.setRemoteSubmixOn(on, REMOTE_SUBMIX_ADDRESS);
- }
- }
-
private void handleStateChanged(boolean enabled) {
mWifiP2pEnabled = enabled;
updateWfdEnableState();
diff --git a/services/java/com/android/server/dreams/DreamManagerService.java b/services/java/com/android/server/dreams/DreamManagerService.java
index 21e54fe..b6e7781 100644
--- a/services/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/java/com/android/server/dreams/DreamManagerService.java
@@ -86,7 +86,13 @@ public final class DreamManagerService extends IDreamManager.Stub {
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+ if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump DreamManager from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid());
+ return;
+ }
pw.println("DREAM MANAGER (dumpsys dreams)");
pw.println();
diff --git a/services/java/com/android/server/location/FlpHardwareProvider.java b/services/java/com/android/server/location/FlpHardwareProvider.java
index 226c18c..ebeccfb 100644
--- a/services/java/com/android/server/location/FlpHardwareProvider.java
+++ b/services/java/com/android/server/location/FlpHardwareProvider.java
@@ -16,12 +16,13 @@
package com.android.server.location;
+import android.hardware.location.GeofenceHardware;
import android.hardware.location.GeofenceHardwareImpl;
+import android.hardware.location.GeofenceHardwareRequestParcelable;
import android.hardware.location.IFusedLocationHardware;
import android.hardware.location.IFusedLocationHardwareSink;
import android.location.IFusedGeofenceHardware;
import android.location.FusedBatchOptions;
-import android.location.Geofence;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
@@ -49,6 +50,15 @@ public class FlpHardwareProvider {
private final Context mContext;
private final Object mLocationSinkLock = new Object();
+ // FlpHal result codes, they must be equal to the ones in fused_location.h
+ private static final int FLP_RESULT_SUCCESS = 0;
+ private static final int FLP_RESULT_ERROR = -1;
+ private static final int FLP_RESULT_INSUFFICIENT_MEMORY = -2;
+ private static final int FLP_RESULT_TOO_MANY_GEOFENCES = -3;
+ private static final int FLP_RESULT_ID_EXISTS = -4;
+ private static final int FLP_RESULT_ID_UNKNOWN = -5;
+ private static final int FLP_RESULT_INVALID_GEOFENCE_TRANSITION = -6;
+
public static FlpHardwareProvider getInstance(Context context) {
if (sSingletonInstance == null) {
sSingletonInstance = new FlpHardwareProvider(context);
@@ -120,29 +130,46 @@ public class FlpHardwareProvider {
Location location,
int transition,
long timestamp,
- int sourcesUsed
- ) {
- // TODO: [GeofenceIntegration] change GeofenceHardwareImpl to accept a location object
+ int sourcesUsed) {
+ getGeofenceHardwareSink().reportGeofenceTransition(
+ geofenceId,
+ updateLocationInformation(location),
+ transition,
+ timestamp,
+ GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE,
+ sourcesUsed);
}
private void onGeofenceMonitorStatus(int status, int source, Location location) {
- // TODO: [GeofenceIntegration]
+ getGeofenceHardwareSink().reportGeofenceMonitorStatus(
+ GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE,
+ status,
+ updateLocationInformation(location),
+ source);
}
private void onGeofenceAdd(int geofenceId, int result) {
- // TODO: [GeofenceIntegration] map between GPS and FLP results to pass a consistent status
+ getGeofenceHardwareSink().reportGeofenceAddStatus(
+ geofenceId,
+ translateToGeofenceHardwareStatus(result));
}
private void onGeofenceRemove(int geofenceId, int result) {
- // TODO: [GeofenceIntegration] map between GPS and FLP results to pass a consistent status
+ getGeofenceHardwareSink().reportGeofenceRemoveStatus(
+ geofenceId,
+ translateToGeofenceHardwareStatus(result));
}
private void onGeofencePause(int geofenceId, int result) {
- // TODO; [GeofenceIntegration] map between GPS and FLP results
+ getGeofenceHardwareSink().reportGeofencePauseStatus(
+ geofenceId,
+ translateToGeofenceHardwareStatus(result));
}
private void onGeofenceResume(int geofenceId, int result) {
- // TODO: [GeofenceIntegration] map between GPS and FLP results
+ getGeofenceHardwareSink().reportGeofenceResumeStatus(
+ geofenceId,
+ translateToGeofenceHardwareStatus(result));
}
/**
@@ -175,7 +202,8 @@ public class FlpHardwareProvider {
// FlpGeofencingInterface members
private native boolean nativeIsGeofencingSupported();
- private native void nativeAddGeofences(int[] geofenceIdsArray, Geofence[] geofencesArray);
+ private native void nativeAddGeofences(
+ GeofenceHardwareRequestParcelable[] geofenceRequestsArray);
private native void nativePauseGeofence(int geofenceId);
private native void nativeResumeGeofence(int geofenceId, int monitorTransitions);
private native void nativeModifyGeofenceOption(
@@ -281,8 +309,8 @@ public class FlpHardwareProvider {
}
@Override
- public void addGeofences(int[] geofenceIdsArray, Geofence[] geofencesArray) {
- nativeAddGeofences(geofenceIdsArray, geofencesArray);
+ public void addGeofences(GeofenceHardwareRequestParcelable[] geofenceRequestsArray) {
+ nativeAddGeofences(geofenceRequestsArray);
}
@Override
@@ -305,17 +333,15 @@ public class FlpHardwareProvider {
int lastTransition,
int monitorTransitions,
int notificationResponsiveness,
- int unknownTimer
- ) {
- // TODO: [GeofenceIntegration] set sourcesToUse to the right value
- // TODO: expose sourcesToUse externally when needed
+ int unknownTimer,
+ int sourcesToUse) {
nativeModifyGeofenceOption(
geofenceId,
lastTransition,
monitorTransitions,
notificationResponsiveness,
unknownTimer,
- /* sourcesToUse */ 0xFFFF);
+ sourcesToUse);
}
};
@@ -347,10 +373,39 @@ public class FlpHardwareProvider {
private GeofenceHardwareImpl getGeofenceHardwareSink() {
if (mGeofenceHardwareSink == null) {
- // TODO: [GeofenceIntegration] we need to register ourselves with GeofenceHardwareImpl
mGeofenceHardwareSink = GeofenceHardwareImpl.getInstance(mContext);
}
return mGeofenceHardwareSink;
}
-} \ No newline at end of file
+
+ private static int translateToGeofenceHardwareStatus(int flpHalResult) {
+ switch(flpHalResult) {
+ case FLP_RESULT_SUCCESS:
+ return GeofenceHardware.GEOFENCE_SUCCESS;
+ case FLP_RESULT_ERROR:
+ return GeofenceHardware.GEOFENCE_FAILURE;
+ // TODO: uncomment this once the ERROR definition is marked public
+ //case FLP_RESULT_INSUFFICIENT_MEMORY:
+ // return GeofenceHardware.GEOFENCE_ERROR_INSUFFICIENT_MEMORY;
+ case FLP_RESULT_TOO_MANY_GEOFENCES:
+ return GeofenceHardware.GEOFENCE_ERROR_TOO_MANY_GEOFENCES;
+ case FLP_RESULT_ID_EXISTS:
+ return GeofenceHardware.GEOFENCE_ERROR_ID_EXISTS;
+ case FLP_RESULT_ID_UNKNOWN:
+ return GeofenceHardware.GEOFENCE_ERROR_ID_UNKNOWN;
+ case FLP_RESULT_INVALID_GEOFENCE_TRANSITION:
+ return GeofenceHardware.GEOFENCE_ERROR_INVALID_TRANSITION;
+ default:
+ Log.e(TAG, String.format("Invalid FlpHal result code: %d", flpHalResult));
+ return GeofenceHardware.GEOFENCE_FAILURE;
+ }
+ }
+
+ private Location updateLocationInformation(Location location) {
+ location.setProvider(LocationManager.FUSED_PROVIDER);
+ // set the elapsed time-stamp just as GPS provider does
+ location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
+ return location;
+ }
+}
diff --git a/services/java/com/android/server/location/GeofenceProxy.java b/services/java/com/android/server/location/GeofenceProxy.java
index f6be27b..a86c923 100644
--- a/services/java/com/android/server/location/GeofenceProxy.java
+++ b/services/java/com/android/server/location/GeofenceProxy.java
@@ -22,6 +22,7 @@ import android.hardware.location.GeofenceHardwareService;
import android.hardware.location.IGeofenceHardware;
import android.location.IGeofenceProvider;
import android.location.IGpsGeofenceHardware;
+import android.location.IFusedGeofenceHardware;
import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
@@ -44,6 +45,7 @@ public final class GeofenceProxy {
private Context mContext;
private IGeofenceHardware mGeofenceHardware;
private IGpsGeofenceHardware mGpsGeofenceHardware;
+ private IFusedGeofenceHardware mFusedGeofenceHardware;
private static final int GEOFENCE_PROVIDER_CONNECTED = 1;
private static final int GEOFENCE_HARDWARE_CONNECTED = 2;
@@ -60,9 +62,11 @@ public final class GeofenceProxy {
public static GeofenceProxy createAndBind(Context context,
int overlaySwitchResId, int defaultServicePackageNameResId,
- int initialPackageNamesResId, Handler handler, IGpsGeofenceHardware gpsGeofence) {
+ int initialPackageNamesResId, Handler handler, IGpsGeofenceHardware gpsGeofence,
+ IFusedGeofenceHardware fusedGeofenceHardware) {
GeofenceProxy proxy = new GeofenceProxy(context, overlaySwitchResId,
- defaultServicePackageNameResId, initialPackageNamesResId, handler, gpsGeofence);
+ defaultServicePackageNameResId, initialPackageNamesResId, handler, gpsGeofence,
+ fusedGeofenceHardware);
if (proxy.bindGeofenceProvider()) {
return proxy;
} else {
@@ -72,11 +76,13 @@ public final class GeofenceProxy {
private GeofenceProxy(Context context,
int overlaySwitchResId, int defaultServicePackageNameResId,
- int initialPackageNamesResId, Handler handler, IGpsGeofenceHardware gpsGeofence) {
+ int initialPackageNamesResId, Handler handler, IGpsGeofenceHardware gpsGeofence,
+ IFusedGeofenceHardware fusedGeofenceHardware) {
mContext = context;
mServiceWatcher = new ServiceWatcher(context, TAG, SERVICE_ACTION, overlaySwitchResId,
defaultServicePackageNameResId, initialPackageNamesResId, mRunnable, handler);
mGpsGeofenceHardware = gpsGeofence;
+ mFusedGeofenceHardware = fusedGeofenceHardware;
bindHardwareGeofence();
}
@@ -123,6 +129,13 @@ public final class GeofenceProxy {
}
}
+ private void setFusedGeofence() {
+ try {
+ mGeofenceHardware.setFusedGeofenceHardware(mFusedGeofenceHardware);
+ } catch(RemoteException e) {
+ Log.e(TAG, "Error while connecting to GeofenceHardwareService");
+ }
+ }
// This needs to be reworked, when more services get added,
// Might need a state machine or add a framework utility class,
@@ -142,6 +155,7 @@ public final class GeofenceProxy {
break;
case GEOFENCE_HARDWARE_CONNECTED:
setGpsGeofence();
+ setFusedGeofence();
mGeofenceHardwareConnected = true;
if (mGeofenceProviderConnected) {
setGeofenceHardwareInProvider();
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 38453c8..6053c61 100644
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -24,9 +24,10 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
+import android.hardware.location.GeofenceHardware;
import android.hardware.location.GeofenceHardwareImpl;
-import android.hardware.location.IGeofenceHardware;
import android.location.Criteria;
+import android.location.FusedBatchOptions;
import android.location.IGpsGeofenceHardware;
import android.location.IGpsStatusListener;
import android.location.IGpsStatusProvider;
@@ -195,6 +196,17 @@ public class GpsLocationProvider implements LocationProviderInterface {
private static final String PROPERTIES_FILE = "/etc/gps.conf";
+ private static final int GPS_GEOFENCE_UNAVAILABLE = 1<<0L;
+ private static final int GPS_GEOFENCE_AVAILABLE = 1<<1L;
+
+ // GPS Geofence errors. Should match gps.h constants.
+ private static final int GPS_GEOFENCE_OPERATION_SUCCESS = 0;
+ private static final int GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES = 100;
+ private static final int GPS_GEOFENCE_ERROR_ID_EXISTS = -101;
+ private static final int GPS_GEOFENCE_ERROR_ID_UNKNOWN = -102;
+ private static final int GPS_GEOFENCE_ERROR_INVALID_TRANSITION = -103;
+ private static final int GPS_GEOFENCE_ERROR_GENERIC = -149;
+
/** simpler wrapper for ProviderRequest + Worksource */
private static class GpsRequest {
public ProviderRequest request;
@@ -501,7 +513,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
LocationManager locManager =
(LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
locManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER,
- 0, 0, new NetworkLocationListener(), mHandler.getLooper());
+ 0, 0, new NetworkLocationListener(), mHandler.getLooper());
}
});
}
@@ -1405,6 +1417,62 @@ public class GpsLocationProvider implements LocationProviderInterface {
}
/**
+ * Helper method to construct a location object.
+ */
+ private Location buildLocation(
+ int flags,
+ double latitude,
+ double longitude,
+ double altitude,
+ float speed,
+ float bearing,
+ float accuracy,
+ long timestamp) {
+ Location location = new Location(LocationManager.GPS_PROVIDER);
+ if((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
+ location.setLatitude(latitude);
+ location.setLongitude(longitude);
+ location.setTime(timestamp);
+ location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
+ }
+ if((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
+ location.setAltitude(altitude);
+ }
+ if((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
+ location.setSpeed(speed);
+ }
+ if((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
+ location.setBearing(bearing);
+ }
+ if((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
+ location.setAccuracy(accuracy);
+ }
+ return location;
+ }
+
+ /**
+ * Converts the GPS HAL status to the internal Geofence Hardware status.
+ */
+ private int getGeofenceStatus(int status) {
+ switch(status) {
+ case GPS_GEOFENCE_OPERATION_SUCCESS:
+ return GeofenceHardware.GEOFENCE_SUCCESS;
+ case GPS_GEOFENCE_ERROR_GENERIC:
+ return GeofenceHardware.GEOFENCE_FAILURE;
+ case GPS_GEOFENCE_ERROR_ID_EXISTS:
+ return GeofenceHardware.GEOFENCE_ERROR_ID_EXISTS;
+ case GPS_GEOFENCE_ERROR_INVALID_TRANSITION:
+ return GeofenceHardware.GEOFENCE_ERROR_INVALID_TRANSITION;
+ case GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES:
+ return GeofenceHardware.GEOFENCE_ERROR_TOO_MANY_GEOFENCES;
+ case GPS_GEOFENCE_ERROR_ID_UNKNOWN:
+ return GeofenceHardware.GEOFENCE_ERROR_ID_UNKNOWN;
+ default:
+ return -1;
+ }
+ }
+
+ /**
* Called from native to report GPS Geofence transition
* All geofence callbacks are called on the same thread
*/
@@ -1414,8 +1482,22 @@ public class GpsLocationProvider implements LocationProviderInterface {
if (mGeofenceHardwareImpl == null) {
mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
}
- mGeofenceHardwareImpl.reportGpsGeofenceTransition(geofenceId, flags, latitude, longitude,
- altitude, speed, bearing, accuracy, timestamp, transition, transitionTimestamp);
+ Location location = buildLocation(
+ flags,
+ latitude,
+ longitude,
+ altitude,
+ speed,
+ bearing,
+ accuracy,
+ timestamp);
+ mGeofenceHardwareImpl.reportGeofenceTransition(
+ geofenceId,
+ location,
+ transition,
+ transitionTimestamp,
+ GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
+ FusedBatchOptions.SourceTechnologies.GNSS);
}
/**
@@ -1427,8 +1509,24 @@ public class GpsLocationProvider implements LocationProviderInterface {
if (mGeofenceHardwareImpl == null) {
mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
}
- mGeofenceHardwareImpl.reportGpsGeofenceStatus(status, flags, latitude, longitude, altitude,
- speed, bearing, accuracy, timestamp);
+ Location location = buildLocation(
+ flags,
+ latitude,
+ longitude,
+ altitude,
+ speed,
+ bearing,
+ accuracy,
+ timestamp);
+ int monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
+ if(status == GPS_GEOFENCE_AVAILABLE) {
+ monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE;
+ }
+ mGeofenceHardwareImpl.reportGeofenceMonitorStatus(
+ GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
+ monitorStatus,
+ location,
+ FusedBatchOptions.SourceTechnologies.GNSS);
}
/**
@@ -1438,7 +1536,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
if (mGeofenceHardwareImpl == null) {
mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
}
- mGeofenceHardwareImpl.reportGpsGeofenceAddStatus(geofenceId, status);
+ mGeofenceHardwareImpl.reportGeofenceAddStatus(geofenceId, getGeofenceStatus(status));
}
/**
@@ -1448,7 +1546,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
if (mGeofenceHardwareImpl == null) {
mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
}
- mGeofenceHardwareImpl.reportGpsGeofenceRemoveStatus(geofenceId, status);
+ mGeofenceHardwareImpl.reportGeofenceRemoveStatus(geofenceId, getGeofenceStatus(status));
}
/**
@@ -1458,7 +1556,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
if (mGeofenceHardwareImpl == null) {
mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
}
- mGeofenceHardwareImpl.reportGpsGeofencePauseStatus(geofenceId, status);
+ mGeofenceHardwareImpl.reportGeofencePauseStatus(geofenceId, getGeofenceStatus(status));
}
/**
@@ -1468,7 +1566,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
if (mGeofenceHardwareImpl == null) {
mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
}
- mGeofenceHardwareImpl.reportGpsGeofenceResumeStatus(geofenceId, status);
+ mGeofenceHardwareImpl.reportGeofenceResumeStatus(geofenceId, getGeofenceStatus(status));
}
//=============================================================
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 656080b..78c1c79 100755
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -1792,8 +1792,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+ @Override
public int[] getPackageGids(String packageName) {
- final boolean enforcedDefault = isPermissionEnforcedDefault(READ_EXTERNAL_STORAGE);
// reader
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(packageName);
@@ -1801,17 +1801,7 @@ public class PackageManagerService extends IPackageManager.Stub {
Log.v(TAG, "getPackageGids" + packageName + ": " + p);
if (p != null) {
final PackageSetting ps = (PackageSetting)p.mExtras;
- final SharedUserSetting suid = ps.sharedUser;
- int[] gids = suid != null ? suid.gids : ps.gids;
-
- // include GIDs for any unenforced permissions
- if (!isPermissionEnforcedLocked(READ_EXTERNAL_STORAGE, enforcedDefault)) {
- final BasePermission basePerm = mSettings.mPermissions.get(
- READ_EXTERNAL_STORAGE);
- gids = appendInts(gids, basePerm.gids);
- }
-
- return gids;
+ return ps.getGids();
}
}
// stupid thing to indicate an error.
@@ -2132,7 +2122,6 @@ public class PackageManagerService extends IPackageManager.Stub {
}
public int checkPermission(String permName, String pkgName) {
- final boolean enforcedDefault = isPermissionEnforcedDefault(permName);
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(pkgName);
if (p != null && p.mExtras != null) {
@@ -2145,15 +2134,11 @@ public class PackageManagerService extends IPackageManager.Stub {
return PackageManager.PERMISSION_GRANTED;
}
}
- if (!isPermissionEnforcedLocked(permName, enforcedDefault)) {
- return PackageManager.PERMISSION_GRANTED;
- }
}
return PackageManager.PERMISSION_DENIED;
}
public int checkUidPermission(String permName, int uid) {
- final boolean enforcedDefault = isPermissionEnforcedDefault(permName);
synchronized (mPackages) {
Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
if (obj != null) {
@@ -2167,9 +2152,6 @@ public class PackageManagerService extends IPackageManager.Stub {
return PackageManager.PERMISSION_GRANTED;
}
}
- if (!isPermissionEnforcedLocked(permName, enforcedDefault)) {
- return PackageManager.PERMISSION_GRANTED;
- }
}
return PackageManager.PERMISSION_DENIED;
}
@@ -11112,42 +11094,9 @@ public class PackageManagerService extends IPackageManager.Stub {
}
@Override
+ @Deprecated
public boolean isPermissionEnforced(String permission) {
- final boolean enforcedDefault = isPermissionEnforcedDefault(permission);
- synchronized (mPackages) {
- return isPermissionEnforcedLocked(permission, enforcedDefault);
- }
- }
-
- /**
- * Check if given permission should be enforced by default. Should always be
- * called outside of {@link #mPackages} lock.
- */
- private boolean isPermissionEnforcedDefault(String permission) {
- if (READ_EXTERNAL_STORAGE.equals(permission)) {
- return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
- android.provider.Settings.Global.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT, 0)
- != 0;
- } else {
- return true;
- }
- }
-
- /**
- * Check if user has requested that given permission be enforced, using
- * given default if undefined.
- */
- private boolean isPermissionEnforcedLocked(String permission, boolean enforcedDefault) {
- if (READ_EXTERNAL_STORAGE.equals(permission)) {
- if (mSettings.mReadExternalStorageEnforced != null) {
- return mSettings.mReadExternalStorageEnforced;
- } else {
- // User hasn't defined; fall back to secure default
- return enforcedDefault;
- }
- } else {
- return true;
- }
+ return true;
}
public boolean isStorageLow() {
diff --git a/services/java/com/android/server/pm/PackageSetting.java b/services/java/com/android/server/pm/PackageSetting.java
index f7f0870..b6f9f5b 100644
--- a/services/java/com/android/server/pm/PackageSetting.java
+++ b/services/java/com/android/server/pm/PackageSetting.java
@@ -52,4 +52,8 @@ final class PackageSetting extends PackageSettingBase {
+ Integer.toHexString(System.identityHashCode(this))
+ " " + name + "/" + appId + "}";
}
-} \ No newline at end of file
+
+ public int[] getGids() {
+ return sharedUser != null ? sharedUser.gids : gids;
+ }
+}
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index e78362b..e18202b 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -1385,9 +1385,10 @@ final class Settings {
StringBuilder sb = new StringBuilder();
for (final PackageSetting pkg : mPackages.values()) {
- ApplicationInfo ai = pkg.pkg.applicationInfo;
- String dataPath = ai.dataDir;
- boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+ final ApplicationInfo ai = pkg.pkg.applicationInfo;
+ final String dataPath = ai.dataDir;
+ final boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+ final int[] gids = pkg.getGids();
// Avoid any application that has a space in its path
// or that is handled by the system.
@@ -1401,6 +1402,7 @@ final class Settings {
// debugFlag - 0 or 1 if the package is debuggable.
// dataPath - path to package's data path
// seinfo - seinfo label for the app (assigned at install time)
+ // gids - supplementary gids this app launches with
//
// NOTE: We prefer not to expose all ApplicationInfo flags for now.
//
@@ -1417,6 +1419,16 @@ final class Settings {
sb.append(dataPath);
sb.append(" ");
sb.append(ai.seinfo);
+ sb.append(" ");
+ if (gids != null && gids.length > 0) {
+ sb.append(gids[0]);
+ for (int i = 1; i < gids.length; i++) {
+ sb.append(",");
+ sb.append(gids[i]);
+ }
+ } else {
+ sb.append("none");
+ }
sb.append("\n");
str.write(sb.toString().getBytes());
}
@@ -1425,6 +1437,7 @@ final class Settings {
str.close();
journal.commit();
} catch (Exception e) {
+ Log.wtf(TAG, "Failed to write packages.list", e);
IoUtils.closeQuietly(str);
journal.rollback();
}
diff --git a/services/java/com/android/server/print/RemotePrintService.java b/services/java/com/android/server/print/RemotePrintService.java
index 322de6c..5c68460 100644
--- a/services/java/com/android/server/print/RemotePrintService.java
+++ b/services/java/com/android/server/print/RemotePrintService.java
@@ -30,8 +30,6 @@ import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.print.IPrinterDiscoverySessionController;
-import android.print.IPrinterDiscoverySessionObserver;
import android.print.PrintJobInfo;
import android.print.PrintManager;
import android.print.PrinterId;
@@ -79,6 +77,10 @@ final class RemotePrintService implements DeathRecipient {
private boolean mDestroyed;
+ private boolean mAllPrintJobsHandled;
+
+ private boolean mHasPrinterDiscoverySession;
+
public RemotePrintService(Context context, ComponentName componentName, int userId,
RemotePrintSpooler spooler) {
mContext = context;
@@ -97,6 +99,8 @@ final class RemotePrintService implements DeathRecipient {
private void handleDestroy() {
throwIfDestroyed();
ensureUnbound();
+ mAllPrintJobsHandled = false;
+ mHasPrinterDiscoverySession = false;
mDestroyed = true;
}
@@ -110,17 +114,27 @@ final class RemotePrintService implements DeathRecipient {
}
private void handleBinderDied() {
+ mAllPrintJobsHandled = false;
+ mHasPrinterDiscoverySession = false;
+ mPendingCommands.clear();
ensureUnbound();
}
private void handleOnAllPrintJobsHandled() {
throwIfDestroyed();
+
+ mAllPrintJobsHandled = true;
+
if (isBound()) {
if (DEBUG) {
Slog.i(LOG_TAG, "[user: " + mUserId + "] handleOnAllPrintJobsHandled()");
}
- // If bound and all the work is completed, then unbind.
- ensureUnbound();
+
+ // If the service has a printer discovery session
+ // created we should not disconnect from it just yet.
+ if (!mHasPrinterDiscoverySession) {
+ ensureUnbound();
+ }
}
}
@@ -152,6 +166,9 @@ final class RemotePrintService implements DeathRecipient {
private void handleOnPrintJobQueued(final PrintJobInfo printJob) {
throwIfDestroyed();
+
+ mAllPrintJobsHandled = false;
+
if (!isBound()) {
ensureBound();
mPendingCommands.add(new Runnable() {
@@ -172,20 +189,18 @@ final class RemotePrintService implements DeathRecipient {
}
}
- public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
- mHandler.obtainMessage(MyHandler.MSG_CREATE_PRINTER_DISCOVERY_SESSION,
- observer).sendToTarget();
+ public void createPrinterDiscoverySession() {
+ mHandler.sendEmptyMessage(MyHandler.MSG_CREATE_PRINTER_DISCOVERY_SESSION);
}
- private void handleCreatePrinterDiscoverySession(
- final IPrinterDiscoverySessionObserver observer) {
+ private void handleCreatePrinterDiscoverySession() {
throwIfDestroyed();
if (!isBound()) {
ensureBound();
mPendingCommands.add(new Runnable() {
@Override
public void run() {
- handleCreatePrinterDiscoverySession(observer);
+ handleCreatePrinterDiscoverySession();
}
});
} else {
@@ -193,9 +208,126 @@ final class RemotePrintService implements DeathRecipient {
Slog.i(LOG_TAG, "[user: " + mUserId + "] createPrinterDiscoverySession()");
}
try {
- mPrintService.createPrinterDiscoverySession(observer);
+ mPrintService.createPrinterDiscoverySession();
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error creating printer dicovery session.", re);
+ }
+
+ mHasPrinterDiscoverySession = true;
+ }
+ }
+
+ public void destroyPrinterDiscoverySession() {
+ mHandler.sendEmptyMessage(MyHandler.MSG_DESTROY_PRINTER_DISCOVERY_SESSION);
+ }
+
+ private void handleDestroyPrinterDiscoverySession() {
+ throwIfDestroyed();
+ if (!isBound()) {
+ ensureBound();
+ mPendingCommands.add(new Runnable() {
+ @Override
+ public void run() {
+ handleDestroyPrinterDiscoverySession();
+ }
+ });
+ } else {
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "[user: " + mUserId + "] destroyPrinterDiscoverySession()");
+ }
+
+ mHasPrinterDiscoverySession = false;
+
+ try {
+ mPrintService.destroyPrinterDiscoverySession();
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error destroying printer dicovery session.", re);
+ }
+
+ // If the service has no print jobs and no active discovery
+ // session anymore we should disconnect from it.
+ if (mAllPrintJobsHandled) {
+ ensureUnbound();
+ }
+ }
+ }
+
+ public void startPrinterDiscovery(List<PrinterId> priorityList) {
+ mHandler.obtainMessage(MyHandler.MSG_START_PRINTER_DISCOVERY,
+ priorityList).sendToTarget();
+ }
+
+ private void handleStartPrinterDiscovery(final List<PrinterId> priorityList) {
+ throwIfDestroyed();
+ if (!isBound()) {
+ ensureBound();
+ mPendingCommands.add(new Runnable() {
+ @Override
+ public void run() {
+ handleStartPrinterDiscovery(priorityList);
+ }
+ });
+ } else {
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "[user: " + mUserId + "] startPrinterDiscovery()");
+ }
+ try {
+ mPrintService.startPrinterDiscovery(priorityList);
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error starting printer dicovery.", re);
+ }
+ }
+ }
+
+ public void stopPrinterDiscovery() {
+ mHandler.sendEmptyMessage(MyHandler.MSG_STOP_PRINTER_DISCOVERY);
+ }
+
+ private void handleStopPrinterDiscovery() {
+ throwIfDestroyed();
+ if (!isBound()) {
+ ensureBound();
+ mPendingCommands.add(new Runnable() {
+ @Override
+ public void run() {
+ handleStopPrinterDiscovery();
+ }
+ });
+ } else {
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "[user: " + mUserId + "] stopPrinterDiscovery()");
+ }
+ try {
+ mPrintService.stopPrinterDiscovery();
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error stopping printer dicovery.", re);
+ }
+ }
+ }
+
+ public void requestPrinterUpdate(PrinterId printerId) {
+ mHandler.obtainMessage(MyHandler.MSG_REQUEST_PRINTER_UPDATE,
+ printerId).sendToTarget();
+ }
+
+ private void handleRequestPrinterUpdate(final PrinterId printerId) {
+ throwIfDestroyed();
+ if (!isBound()) {
+ ensureBound();
+ mPendingCommands.add(new Runnable() {
+ @Override
+ public void run() {
+ handleRequestPrinterUpdate(printerId);
+ }
+ });
+ } else {
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "[user: " + mUserId + "] requestPrinterUpdate()");
+ }
+ try {
+ mPrintService.requestPrinterUpdate(printerId);
} catch (RemoteException re) {
- Slog.e(LOG_TAG, "Error announcing start printer dicovery.", re);
+ Slog.e(LOG_TAG, "Error requesting a printer update.", re);
}
}
}
@@ -278,20 +410,47 @@ final class RemotePrintService implements DeathRecipient {
}
private final class MyHandler extends Handler {
- public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 1;
- public static final int MSG_ON_REQUEST_CANCEL_PRINT_JOB = 2;
- public static final int MSG_ON_PRINT_JOB_QUEUED = 3;
- public static final int MSG_CREATE_PRINTER_DISCOVERY_SESSION = 4;
- public static final int MSG_DESTROY = 6;
- public static final int MSG_BINDER_DIED = 7;
+ public static final int MSG_CREATE_PRINTER_DISCOVERY_SESSION = 1;
+ public static final int MSG_DESTROY_PRINTER_DISCOVERY_SESSION = 2;
+ public static final int MSG_START_PRINTER_DISCOVERY = 3;
+ public static final int MSG_STOP_PRINTER_DISCOVERY = 4;
+ public static final int MSG_REQUEST_PRINTER_UPDATE = 5;
+ public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 6;
+ public static final int MSG_ON_REQUEST_CANCEL_PRINT_JOB = 7;
+ public static final int MSG_ON_PRINT_JOB_QUEUED = 8;
+ public static final int MSG_DESTROY = 9;
+ public static final int MSG_BINDER_DIED = 10;
public MyHandler(Looper looper) {
super(looper, null, false);
}
@Override
+ @SuppressWarnings("unchecked")
public void handleMessage(Message message) {
switch (message.what) {
+ case MSG_CREATE_PRINTER_DISCOVERY_SESSION: {
+ handleCreatePrinterDiscoverySession();
+ } break;
+
+ case MSG_DESTROY_PRINTER_DISCOVERY_SESSION: {
+ handleDestroyPrinterDiscoverySession();
+ } break;
+
+ case MSG_START_PRINTER_DISCOVERY: {
+ List<PrinterId> priorityList = (ArrayList<PrinterId>) message.obj;
+ handleStartPrinterDiscovery(priorityList);
+ } break;
+
+ case MSG_STOP_PRINTER_DISCOVERY: {
+ handleStopPrinterDiscovery();
+ } break;
+
+ case MSG_REQUEST_PRINTER_UPDATE: {
+ PrinterId printerId = (PrinterId) message.obj;
+ handleRequestPrinterUpdate(printerId);
+ } break;
+
case MSG_ON_ALL_PRINT_JOBS_HANDLED: {
handleOnAllPrintJobsHandled();
} break;
@@ -306,13 +465,6 @@ final class RemotePrintService implements DeathRecipient {
handleOnPrintJobQueued(printJob);
} break;
- case MSG_CREATE_PRINTER_DISCOVERY_SESSION: {
- IPrinterDiscoverySessionObserver observer =
- (IPrinterDiscoverySessionObserver) message.obj;
- handleCreatePrinterDiscoverySession(new SecurePrinterDiscoverySessionObserver(
- mComponentName, observer));
- } break;
-
case MSG_DESTROY: {
handleDestroy();
} break;
@@ -362,7 +514,7 @@ final class RemotePrintService implements DeathRecipient {
}
@Override
- public boolean setPrintJobState(int printJobId, int state, CharSequence error) {
+ public boolean setPrintJobState(int printJobId, int state, String error) {
RemotePrintService service = mWeakService.get();
if (service != null) {
final long identity = Binder.clearCallingIdentity();
@@ -401,79 +553,70 @@ final class RemotePrintService implements DeathRecipient {
}
}
}
- }
-
- private static final class SecurePrinterDiscoverySessionObserver
- extends IPrinterDiscoverySessionObserver.Stub {
- private final ComponentName mComponentName;
-
- private final IPrinterDiscoverySessionObserver mDecoratedObsever;
-
- public SecurePrinterDiscoverySessionObserver(ComponentName componentName,
- IPrinterDiscoverySessionObserver observer) {
- mComponentName = componentName;
- mDecoratedObsever = observer;
- }
@Override
public void onPrintersAdded(List<PrinterInfo> printers) {
- throwIfPrinterIdsForPrinterInfoTampered(printers);
- try {
- mDecoratedObsever.onPrintersAdded(printers);
- } catch (RemoteException re) {
- Slog.e(LOG_TAG, "Error delegating to onPrintersAdded", re);
- }
- }
-
- @Override
- public void onPrintersUpdated(List<PrinterInfo> printers) {
- throwIfPrinterIdsForPrinterInfoTampered(printers);
- try {
- mDecoratedObsever.onPrintersUpdated(printers);
- } catch (RemoteException re) {
- Slog.e(LOG_TAG, "Error delegating to onPrintersUpdated.", re);
+ RemotePrintService service = mWeakService.get();
+ if (service != null) {
+ throwIfPrinterIdsForPrinterInfoTampered(service.mComponentName, printers);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ service.mSpooler.onPrintersAdded(printers);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
}
@Override
public void onPrintersRemoved(List<PrinterId> printerIds) {
- throwIfPrinterIdsTampered(printerIds);
- try {
- mDecoratedObsever.onPrintersRemoved(printerIds);
- } catch (RemoteException re) {
- Slog.e(LOG_TAG, "Error delegating to onPrintersRemoved", re);
+ RemotePrintService service = mWeakService.get();
+ if (service != null) {
+ throwIfPrinterIdsTampered(service.mComponentName, printerIds);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ service.mSpooler.onPrintersRemoved(printerIds);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
}
@Override
- public void setController(IPrinterDiscoverySessionController controller) {
- try {
- mDecoratedObsever.setController(controller);
- } catch (RemoteException re) {
- Slog.e(LOG_TAG, "Error setting controller", re);
+ public void onPrintersUpdated(List<PrinterInfo> printers) {
+ RemotePrintService service = mWeakService.get();
+ if (service != null) {
+ throwIfPrinterIdsForPrinterInfoTampered(service.mComponentName, printers);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ service.mSpooler.onPrintersUpdated(printers);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
}
- private void throwIfPrinterIdsForPrinterInfoTampered(
+ private void throwIfPrinterIdsForPrinterInfoTampered(ComponentName serviceName,
List<PrinterInfo> printerInfos) {
final int printerInfoCount = printerInfos.size();
for (int i = 0; i < printerInfoCount; i++) {
PrinterId printerId = printerInfos.get(i).getId();
- throwIfPrinterIdTampered(printerId);
+ throwIfPrinterIdTampered(serviceName, printerId);
}
}
- private void throwIfPrinterIdsTampered(List<PrinterId> printerIds) {
+ private void throwIfPrinterIdsTampered(ComponentName serviceName,
+ List<PrinterId> printerIds) {
final int printerIdCount = printerIds.size();
for (int i = 0; i < printerIdCount; i++) {
PrinterId printerId = printerIds.get(i);
- throwIfPrinterIdTampered(printerId);
+ throwIfPrinterIdTampered(serviceName, printerId);
}
}
- private void throwIfPrinterIdTampered(PrinterId printerId) {
+ private void throwIfPrinterIdTampered(ComponentName serviceName, PrinterId printerId) {
if (printerId == null || printerId.getServiceName() == null
- || !printerId.getServiceName().equals(mComponentName)) {
+ || !printerId.getServiceName().equals(serviceName)) {
throw new IllegalArgumentException("Invalid printer id: " + printerId);
}
}
diff --git a/services/java/com/android/server/print/RemotePrintSpooler.java b/services/java/com/android/server/print/RemotePrintSpooler.java
index c932e9b..d261288 100644
--- a/services/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/java/com/android/server/print/RemotePrintSpooler.java
@@ -32,9 +32,10 @@ import android.print.IPrintDocumentAdapter;
import android.print.IPrintSpooler;
import android.print.IPrintSpoolerCallbacks;
import android.print.IPrintSpoolerClient;
-import android.print.IPrinterDiscoverySessionObserver;
import android.print.PrintAttributes;
import android.print.PrintJobInfo;
+import android.print.PrinterId;
+import android.print.PrinterInfo;
import android.util.Slog;
import android.util.TimedRemoteCaller;
@@ -92,7 +93,11 @@ final class RemotePrintSpooler {
public static interface PrintSpoolerCallbacks {
public void onPrintJobQueued(PrintJobInfo printJob);
public void onAllPrintJobsForServiceHandled(ComponentName printService);
- public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer);
+ public void createPrinterDiscoverySession();
+ public void destroyPrinterDiscoverySession();
+ public void startPrinterDiscovery(List<PrinterId> priorityList);
+ public void stopPrinterDiscovery();
+ public void requestPrinterUpdate(PrinterId printerId);
}
public RemotePrintSpooler(Context context, int userId,
@@ -209,7 +214,7 @@ final class RemotePrintSpooler {
return null;
}
- public final boolean setPrintJobState(int printJobId, int state, CharSequence error) {
+ public final boolean setPrintJobState(int printJobId, int state, String error) {
throwIfCalledOnMainThread();
synchronized (mLock) {
throwIfDestroyedLocked();
@@ -300,6 +305,78 @@ final class RemotePrintSpooler {
}
}
+ public final void onPrintersAdded(List<PrinterInfo> printers) {
+ throwIfCalledOnMainThread();
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ mCanUnbind = false;
+ }
+ try {
+ getRemoteInstanceLazy().onPrintersAdded(printers);
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error adding printers.", re);
+ } catch (TimeoutException te) {
+ Slog.e(LOG_TAG, "Error adding printers.", te);
+ } finally {
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
+ + "] onPrintersAdded()");
+ }
+ synchronized (mLock) {
+ mCanUnbind = true;
+ mLock.notifyAll();
+ }
+ }
+ }
+
+ public final void onPrintersRemoved(List<PrinterId> printerIds) {
+ throwIfCalledOnMainThread();
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ mCanUnbind = false;
+ }
+ try {
+ getRemoteInstanceLazy().onPrintersRemoved(printerIds);
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error removing printers.", re);
+ } catch (TimeoutException te) {
+ Slog.e(LOG_TAG, "Error removing printers.", te);
+ } finally {
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
+ + "] onPrintersRemoved()");
+ }
+ synchronized (mLock) {
+ mCanUnbind = true;
+ mLock.notifyAll();
+ }
+ }
+ }
+
+ public final void onPrintersUpdated(List<PrinterInfo> printers) {
+ throwIfCalledOnMainThread();
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ mCanUnbind = false;
+ }
+ try {
+ getRemoteInstanceLazy().onPrintersUpdated(printers);
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error updating printers.", re);
+ } catch (TimeoutException te) {
+ Slog.e(LOG_TAG, "Error updating printers.", te);
+ } finally {
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
+ + "] onPrintersUpdted()");
+ }
+ synchronized (mLock) {
+ mCanUnbind = true;
+ mLock.notifyAll();
+ }
+ }
+ }
+
private IPrintSpooler getRemoteInstanceLazy() throws TimeoutException {
synchronized (mLock) {
if (mRemoteInstance != null) {
@@ -488,7 +565,7 @@ final class RemotePrintSpooler {
}
public boolean setPrintJobState(IPrintSpooler target, int printJobId,
- int status, CharSequence error) throws RemoteException, TimeoutException {
+ int status, String error) throws RemoteException, TimeoutException {
final int sequence = onBeforeRemoteCall();
target.setPrintJobState(printJobId, status, error, mCallback, sequence);
return getResultTimed(sequence);
@@ -597,12 +674,64 @@ final class RemotePrintSpooler {
}
@Override
- public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
+ public void createPrinterDiscoverySession() {
+ RemotePrintSpooler spooler = mWeakSpooler.get();
+ if (spooler != null) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ spooler.mCallbacks.createPrinterDiscoverySession();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
+ @Override
+ public void destroyPrinterDiscoverySession() {
+ RemotePrintSpooler spooler = mWeakSpooler.get();
+ if (spooler != null) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ spooler.mCallbacks.destroyPrinterDiscoverySession();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
+ @Override
+ public void startPrinterDiscovery(List<PrinterId> priorityList) {
+ RemotePrintSpooler spooler = mWeakSpooler.get();
+ if (spooler != null) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ spooler.mCallbacks.startPrinterDiscovery(priorityList);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
+ @Override
+ public void stopPrinterDiscovery() {
+ RemotePrintSpooler spooler = mWeakSpooler.get();
+ if (spooler != null) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ spooler.mCallbacks.stopPrinterDiscovery();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
+ @Override
+ public void requestPrinterUpdate(PrinterId printerId) {
RemotePrintSpooler spooler = mWeakSpooler.get();
if (spooler != null) {
final long identity = Binder.clearCallingIdentity();
try {
- spooler.mCallbacks.createPrinterDiscoverySession(observer);
+ spooler.mCallbacks.requestPrinterUpdate(printerId);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/java/com/android/server/print/UserState.java b/services/java/com/android/server/print/UserState.java
index ffcc9c3..9d7cfdd 100644
--- a/services/java/com/android/server/print/UserState.java
+++ b/services/java/com/android/server/print/UserState.java
@@ -21,8 +21,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.print.IPrinterDiscoverySessionObserver;
import android.print.PrintJobInfo;
+import android.print.PrinterId;
import android.printservice.PrintServiceInfo;
import android.provider.Settings;
import android.text.TextUtils;
@@ -105,7 +105,7 @@ final class UserState implements PrintSpoolerCallbacks {
}
@Override
- public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
+ public void createPrinterDiscoverySession() {
final List<RemotePrintService> services;
synchronized (mLock) {
throwIfDestroyedLocked();
@@ -117,7 +117,73 @@ final class UserState implements PrintSpoolerCallbacks {
final int serviceCount = services.size();
for (int i = 0; i < serviceCount; i++) {
RemotePrintService service = services.get(i);
- service.createPrinterDiscoverySession(observer);
+ service.createPrinterDiscoverySession();
+ }
+ }
+
+ @Override
+ public void destroyPrinterDiscoverySession() {
+ final List<RemotePrintService> services;
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ if (mActiveServices.isEmpty()) {
+ return;
+ }
+ services = new ArrayList<RemotePrintService>(mActiveServices.values());
+ }
+ final int serviceCount = services.size();
+ for (int i = 0; i < serviceCount; i++) {
+ RemotePrintService service = services.get(i);
+ service.destroyPrinterDiscoverySession();
+ }
+ }
+
+ @Override
+ public void startPrinterDiscovery(List<PrinterId> printerIds) {
+ final List<RemotePrintService> services;
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ if (mActiveServices.isEmpty()) {
+ return;
+ }
+ services = new ArrayList<RemotePrintService>(mActiveServices.values());
+ }
+ final int serviceCount = services.size();
+ for (int i = 0; i < serviceCount; i++) {
+ RemotePrintService service = services.get(i);
+ service.startPrinterDiscovery(printerIds);
+ }
+ }
+
+ @Override
+ public void stopPrinterDiscovery() {
+ final List<RemotePrintService> services;
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ if (mActiveServices.isEmpty()) {
+ return;
+ }
+ services = new ArrayList<RemotePrintService>(mActiveServices.values());
+ }
+ final int serviceCount = services.size();
+ for (int i = 0; i < serviceCount; i++) {
+ RemotePrintService service = services.get(i);
+ service.stopPrinterDiscovery();
+ }
+ }
+
+ @Override
+ public void requestPrinterUpdate(PrinterId printerId) {
+ final RemotePrintService service;
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ if (mActiveServices.isEmpty()) {
+ return;
+ }
+ service = mActiveServices.get(printerId.getServiceName());
+ }
+ if (service != null) {
+ service.requestPrinterUpdate(printerId);
}
}
diff --git a/services/java/com/android/server/wifi/WifiService.java b/services/java/com/android/server/wifi/WifiService.java
index 6e0e055..c215f40 100644
--- a/services/java/com/android/server/wifi/WifiService.java
+++ b/services/java/com/android/server/wifi/WifiService.java
@@ -25,18 +25,20 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
+import android.net.DhcpInfo;
+import android.net.DhcpResults;
+import android.net.LinkAddress;
+import android.net.NetworkUtils;
+import android.net.RouteInfo;
import android.net.wifi.IWifiManager;
import android.net.wifi.ScanResult;
+import android.net.wifi.BatchedScanResult;
+import android.net.wifi.BatchedScanSettings;
+import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiStateMachine;
-import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiWatchdogStateMachine;
-import android.net.DhcpInfo;
-import android.net.DhcpResults;
-import android.net.LinkAddress;
-import android.net.NetworkUtils;
-import android.net.RouteInfo;
import android.os.Binder;
import android.os.Handler;
import android.os.Messenger;
@@ -63,6 +65,7 @@ import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Inet4Address;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -121,6 +124,8 @@ public final class WifiService extends IWifiManager.Stub {
/* Tracks the persisted states for wi-fi & airplane mode */
final WifiSettingsStore mSettingsStore;
+ final boolean mBatchedScanSupported;
+
/**
* Asynchronous channel to WifiStateMachine
*/
@@ -246,6 +251,9 @@ public final class WifiService extends IWifiManager.Stub {
mWifiController = new WifiController(mContext, this, wifiThread.getLooper());
mWifiController.start();
+ mBatchedScanSupported = mContext.getResources().getBoolean(
+ R.bool.config_wifi_batched_scan_supported);
+
registerForScanModeChange();
mContext.registerReceiver(
new BroadcastReceiver() {
@@ -314,6 +322,148 @@ public final class WifiService extends IWifiManager.Stub {
mWifiStateMachine.startScan(Binder.getCallingUid(), workSource);
}
+ private class BatchedScanRequest extends DeathRecipient {
+ BatchedScanSettings settings;
+ int uid;
+
+ BatchedScanRequest(BatchedScanSettings settings, IBinder binder, int uid) {
+ super(0, null, binder, null);
+ this.settings = settings;
+ this.uid = uid;
+ }
+ public void binderDied() {
+ stopBatchedScan(settings, mBinder);
+ }
+ public String toString() {
+ return "BatchedScanRequest{settings=" + settings + ", binder=" + mBinder + "}";
+ }
+ }
+
+ private final List<BatchedScanRequest> mBatchedScanners = new ArrayList<BatchedScanRequest>();
+
+ public boolean isBatchedScanSupported() {
+ return mBatchedScanSupported;
+ }
+
+ public void pollBatchedScan() {
+ enforceChangePermission();
+ if (mBatchedScanSupported == false) return;
+ mWifiStateMachine.requestBatchedScanPoll();
+ }
+
+ /**
+ * see {@link android.net.wifi.WifiManager#requestBatchedScan()}
+ */
+ public boolean requestBatchedScan(BatchedScanSettings requested, IBinder binder) {
+ enforceChangePermission();
+ if (mBatchedScanSupported == false) return false;
+ requested = new BatchedScanSettings(requested);
+ if (requested.isInvalid()) return false;
+ BatchedScanRequest r = new BatchedScanRequest(requested, binder, Binder.getCallingUid());
+ synchronized(mBatchedScanners) {
+ mBatchedScanners.add(r);
+ resolveBatchedScannersLocked();
+ }
+ return true;
+ }
+
+ public List<BatchedScanResult> getBatchedScanResults(String callingPackage) {
+ enforceAccessPermission();
+ if (mBatchedScanSupported == false) return new ArrayList<BatchedScanResult>();
+ int userId = UserHandle.getCallingUserId();
+ int uid = Binder.getCallingUid();
+ long ident = Binder.clearCallingIdentity();
+ try {
+ if (mAppOps.noteOp(AppOpsManager.OP_WIFI_SCAN, uid, callingPackage)
+ != AppOpsManager.MODE_ALLOWED) {
+ return new ArrayList<BatchedScanResult>();
+ }
+ int currentUser = ActivityManager.getCurrentUser();
+ if (userId != currentUser) {
+ return new ArrayList<BatchedScanResult>();
+ } else {
+ return mWifiStateMachine.syncGetBatchedScanResultsList();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+
+ public void stopBatchedScan(BatchedScanSettings settings, IBinder binder) {
+ enforceChangePermission();
+ if (mBatchedScanSupported == false) return;
+ synchronized(mBatchedScanners) {
+ BatchedScanRequest found = null;
+ for (BatchedScanRequest r : mBatchedScanners) {
+ if (r.mBinder.equals(binder) && r.settings.equals(settings)) {
+ found = r;
+ break;
+ }
+ }
+ if (found != null) {
+ mBatchedScanners.remove(found);
+ resolveBatchedScannersLocked();
+ }
+ }
+ }
+
+ private void resolveBatchedScannersLocked() {
+ BatchedScanSettings setting = new BatchedScanSettings();
+ setting.scanIntervalSec = BatchedScanSettings.DEFAULT_INTERVAL_SEC;
+ int responsibleUid = 0;
+ setting.channelSet = new ArrayList<String>();
+
+ if (mBatchedScanners.size() == 0) {
+ mWifiStateMachine.setBatchedScanSettings(null, 0);
+ return;
+ }
+
+ for (BatchedScanRequest r : mBatchedScanners) {
+ BatchedScanSettings s = r.settings;
+ if (s.maxScansPerBatch != BatchedScanSettings.UNSPECIFIED &&
+ s.maxScansPerBatch < setting.maxScansPerBatch) {
+ setting.maxScansPerBatch = s.maxScansPerBatch;
+ responsibleUid = r.uid;
+ }
+ if (s.maxApPerScan != BatchedScanSettings.UNSPECIFIED &&
+ s.maxApPerScan > setting.maxApPerScan) {
+ setting.maxApPerScan = s.maxApPerScan;
+ }
+ if (s.scanIntervalSec != BatchedScanSettings.UNSPECIFIED &&
+ s.scanIntervalSec < setting.scanIntervalSec) {
+ setting.scanIntervalSec = s.scanIntervalSec;
+ responsibleUid = r.uid;
+ }
+ if (s.maxApForDistance != BatchedScanSettings.UNSPECIFIED &&
+ s.maxApForDistance > setting.maxApForDistance) {
+ setting.maxApForDistance = s.maxApForDistance;
+ }
+ if (s.channelSet != null) {
+ for (String i : s.channelSet) {
+ if (setting.channelSet.contains(i) == false) setting.channelSet.add(i);
+ }
+ }
+ }
+ if (setting.channelSet.size() == 0) setting.channelSet = null;
+ if (setting.scanIntervalSec < BatchedScanSettings.MIN_INTERVAL_SEC) {
+ setting.scanIntervalSec = BatchedScanSettings.MIN_INTERVAL_SEC;
+ }
+ if (setting.maxScansPerBatch == BatchedScanSettings.UNSPECIFIED) {
+ setting.maxScansPerBatch = BatchedScanSettings.DEFAULT_SCANS_PER_BATCH;
+ }
+ if (setting.maxApPerScan == BatchedScanSettings.UNSPECIFIED) {
+ setting.maxApPerScan = BatchedScanSettings.DEFAULT_AP_PER_SCAN;
+ }
+ if (setting.scanIntervalSec == BatchedScanSettings.UNSPECIFIED) {
+ setting.scanIntervalSec = BatchedScanSettings.DEFAULT_INTERVAL_SEC;
+ }
+ if (setting.maxApForDistance == BatchedScanSettings.UNSPECIFIED) {
+ setting.maxApForDistance = BatchedScanSettings.DEFAULT_AP_FOR_DISTANCE;
+ }
+ mWifiStateMachine.setBatchedScanSettings(setting, responsibleUid);
+ }
+
private void enforceAccessPermission() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE,
"WifiService");
@@ -569,11 +719,11 @@ public final class WifiService extends IWifiManager.Stub {
int userId = UserHandle.getCallingUserId();
int uid = Binder.getCallingUid();
long ident = Binder.clearCallingIdentity();
- if (mAppOps.noteOp(AppOpsManager.OP_WIFI_SCAN, uid, callingPackage)
- != AppOpsManager.MODE_ALLOWED) {
- return new ArrayList<ScanResult>();
- }
try {
+ if (mAppOps.noteOp(AppOpsManager.OP_WIFI_SCAN, uid, callingPackage)
+ != AppOpsManager.MODE_ALLOWED) {
+ return new ArrayList<ScanResult>();
+ }
int currentUser = ActivityManager.getCurrentUser();
if (userId != currentUser) {
return new ArrayList<ScanResult>();
diff --git a/services/jni/com_android_server_location_FlpHardwareProvider.cpp b/services/jni/com_android_server_location_FlpHardwareProvider.cpp
index 48b86db..c871828 100644
--- a/services/jni/com_android_server_location_FlpHardwareProvider.cpp
+++ b/services/jni/com_android_server_location_FlpHardwareProvider.cpp
@@ -261,6 +261,75 @@ static void TranslateFromObject(
}
/*
+ * Helper function to unwrap Geofence structures from the Java Runtime calls.
+ */
+static void TranslateGeofenceFromGeofenceHardwareRequestParcelable(
+ JNIEnv* env,
+ jobject geofenceRequestObject,
+ Geofence& geofence) {
+ jclass geofenceRequestClass = env->GetObjectClass(geofenceRequestObject);
+
+ jmethodID getId = env->GetMethodID(geofenceRequestClass, "getId", "()I");
+ geofence.geofence_id = env->CallIntMethod(geofenceRequestObject, getId);
+
+ jmethodID getType = env->GetMethodID(geofenceRequestClass, "getType", "()I");
+ // this works because GeofenceHardwareRequest.java and fused_location.h have
+ // the same notion of geofence types
+ GeofenceType type = (GeofenceType)env->CallIntMethod(geofenceRequestObject, getType);
+ if(type != TYPE_CIRCLE) {
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+ geofence.data->type = type;
+ GeofenceCircle& circle = geofence.data->geofence.circle;
+
+ jmethodID getLatitude = env->GetMethodID(
+ geofenceRequestClass,
+ "getLatitude",
+ "()D");
+ circle.latitude = env->CallDoubleMethod(geofenceRequestObject, getLatitude);
+
+ jmethodID getLongitude = env->GetMethodID(
+ geofenceRequestClass,
+ "getLongitude",
+ "()D");
+ circle.longitude = env->CallDoubleMethod(geofenceRequestObject, getLongitude);
+
+ jmethodID getRadius = env->GetMethodID(geofenceRequestClass, "getRadius", "()D");
+ circle.radius_m = env->CallDoubleMethod(geofenceRequestObject, getRadius);
+
+ GeofenceOptions* options = geofence.options;
+ jmethodID getMonitorTransitions = env->GetMethodID(
+ geofenceRequestClass,
+ "getMonitorTransitions",
+ "()I");
+ options->monitor_transitions = env->CallIntMethod(
+ geofenceRequestObject,
+ getMonitorTransitions);
+
+ jmethodID getUnknownTimer = env->GetMethodID(
+ geofenceRequestClass,
+ "getUnknownTimer",
+ "()I");
+ options->unknown_timer_ms = env->CallIntMethod(geofenceRequestObject, getUnknownTimer);
+
+ jmethodID getNotificationResponsiveness = env->GetMethodID(
+ geofenceRequestClass,
+ "getNotificationResponsiveness",
+ "()D");
+ options->notification_responsivenes_ms = env->CallIntMethod(
+ geofenceRequestObject,
+ getNotificationResponsiveness);
+
+ jmethodID getLastTransition = env->GetMethodID(
+ geofenceRequestClass,
+ "getLastTransition",
+ "()I");
+ options->last_transition = env->CallIntMethod(geofenceRequestObject, getLastTransition);
+
+ // TODO: set data.sources_to_use when available
+}
+
+/*
* Helper function to transform FlpLocation into a java object.
*/
static void TranslateToObject(const FlpLocation* location, jobject& locationObject) {
@@ -559,7 +628,7 @@ static void Init(JNIEnv* env, jobject obj) {
}
err = module->methods->open(
- module,
+ module,
FUSED_LOCATION_HARDWARE_MODULE_ID, &sHardwareDevice);
if(err != 0) {
ALOGE("Error opening device '%s': %d", FUSED_LOCATION_HARDWARE_MODULE_ID, err);
@@ -749,10 +818,9 @@ static jboolean IsGeofencingSupported() {
static void AddGeofences(
JNIEnv* env,
jobject object,
- jintArray geofenceIdsArray,
- jobjectArray geofencesArray) {
- if(geofencesArray == NULL) {
- ALOGE("Invalid Geofences to add: %p", geofencesArray);
+ jobjectArray geofenceRequestsArray) {
+ if(geofenceRequestsArray == NULL) {
+ ALOGE("Invalid Geofences to add: %p", geofenceRequestsArray);
ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
}
@@ -760,23 +828,32 @@ static void AddGeofences(
ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
}
- jint geofencesCount = env->GetArrayLength(geofenceIdsArray);
- Geofence* geofences = new Geofence[geofencesCount];
+ jint geofenceRequestsCount = env->GetArrayLength(geofenceRequestsArray);
+ if(geofenceRequestsCount == 0) {
+ return;
+ }
+
+ Geofence* geofences = new Geofence[geofenceRequestsCount];
if (geofences == NULL) {
ThrowOnError(env, FLP_RESULT_INSUFFICIENT_MEMORY, __FUNCTION__);
}
- jint* ids = env->GetIntArrayElements(geofenceIdsArray, /* isCopy */ NULL);
- for (int i = 0; i < geofencesCount; ++i) {
- geofences[i].geofence_id = ids[i];
+ for (int i = 0; i < geofenceRequestsCount; ++i) {
+ geofences[i].data = new GeofenceData();
+ geofences[i].options = new GeofenceOptions();
+ jobject geofenceObject = env->GetObjectArrayElement(geofenceRequestsArray, i);
- // TODO: fill in the GeofenceData
-
- // TODO: fill in the GeofenceOptions
+ TranslateGeofenceFromGeofenceHardwareRequestParcelable(env, geofenceObject, geofences[i]);
}
- sFlpGeofencingInterface->add_geofences(geofencesCount, &geofences);
- if (geofences != NULL) delete[] geofences;
+ sFlpGeofencingInterface->add_geofences(geofenceRequestsCount, &geofences);
+ if (geofences != NULL) {
+ for(int i = 0; i < geofenceRequestsCount; ++i) {
+ delete geofences[i].data;
+ delete geofences[i].options;
+ }
+ delete[] geofences;
+ }
}
static void PauseGeofence(JNIEnv* env, jobject object, jint geofenceId) {
@@ -847,41 +924,41 @@ static JNINativeMethod sMethods[] = {
{"nativeCleanup", "()V", reinterpret_cast<void*>(Cleanup)},
{"nativeIsSupported", "()Z", reinterpret_cast<void*>(IsSupported)},
{"nativeGetBatchSize", "()I", reinterpret_cast<void*>(GetBatchSize)},
- {"nativeStartBatching",
- "(ILandroid/location/FusedBatchOptions;)V",
+ {"nativeStartBatching",
+ "(ILandroid/location/FusedBatchOptions;)V",
reinterpret_cast<void*>(StartBatching)},
- {"nativeUpdateBatchingOptions",
- "(ILandroid/location/FusedBatchOptions;)V",
+ {"nativeUpdateBatchingOptions",
+ "(ILandroid/location/FusedBatchOptions;)V",
reinterpret_cast<void*>(UpdateBatchingOptions)},
{"nativeStopBatching", "(I)V", reinterpret_cast<void*>(StopBatching)},
- {"nativeRequestBatchedLocation",
- "(I)V",
+ {"nativeRequestBatchedLocation",
+ "(I)V",
reinterpret_cast<void*>(GetBatchedLocation)},
- {"nativeInjectLocation",
- "(Landroid/location/Location;)V",
+ {"nativeInjectLocation",
+ "(Landroid/location/Location;)V",
reinterpret_cast<void*>(InjectLocation)},
- {"nativeIsDiagnosticSupported",
- "()Z",
+ {"nativeIsDiagnosticSupported",
+ "()Z",
reinterpret_cast<void*>(IsDiagnosticSupported)},
- {"nativeInjectDiagnosticData",
- "(Ljava/lang/String;)V",
+ {"nativeInjectDiagnosticData",
+ "(Ljava/lang/String;)V",
reinterpret_cast<void*>(InjectDiagnosticData)},
- {"nativeIsDeviceContextSupported",
- "()Z",
+ {"nativeIsDeviceContextSupported",
+ "()Z",
reinterpret_cast<void*>(IsDeviceContextSupported)},
- {"nativeInjectDeviceContext",
- "(I)V",
+ {"nativeInjectDeviceContext",
+ "(I)V",
reinterpret_cast<void*>(InjectDeviceContext)},
- {"nativeIsGeofencingSupported",
- "()Z",
+ {"nativeIsGeofencingSupported",
+ "()Z",
reinterpret_cast<void*>(IsGeofencingSupported)},
- {"nativeAddGeofences",
- "([I[Landroid/location/Geofence;)V",
+ {"nativeAddGeofences",
+ "([Landroid/hardware/location/GeofenceHardwareRequestParcelable;)V",
reinterpret_cast<void*>(AddGeofences)},
{"nativePauseGeofence", "(I)V", reinterpret_cast<void*>(PauseGeofence)},
{"nativeResumeGeofence", "(II)V", reinterpret_cast<void*>(ResumeGeofence)},
- {"nativeModifyGeofenceOption",
- "(IIIIII)V",
+ {"nativeModifyGeofenceOption",
+ "(IIIIII)V",
reinterpret_cast<void*>(ModifyGeofenceOption)},
{"nativeRemoveGeofences", "([I)V", reinterpret_cast<void*>(RemoveGeofences)}
};
diff --git a/services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java b/services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java
index dff6661..e44652f 100644
--- a/services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java
+++ b/services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java
@@ -67,7 +67,7 @@ public class SyncStorageEngineTest extends AndroidTestCase {
/**
* Test that we handle the case of a history row being old enough to purge before the
- * correcponding sync is finished. This can happen if the clock changes while we are syncing.
+ * corresponding sync is finished. This can happen if the clock changes while we are syncing.
*
*/
// TODO: this test causes AidlTest to fail. Omit for now
@@ -104,6 +104,17 @@ public class SyncStorageEngineTest extends AndroidTestCase {
engine.clearAndReadState();
assert(engine.getPendingOperationCount() == 1);
+ List<SyncStorageEngine.PendingOperation> pops = engine.getPendingOperations();
+ SyncStorageEngine.PendingOperation popRetrieved = pops.get(0);
+ assertEquals(pop.account, popRetrieved.account);
+ assertEquals(pop.reason, popRetrieved.reason);
+ assertEquals(pop.userId, popRetrieved.userId);
+ assertEquals(pop.syncSource, popRetrieved.syncSource);
+ assertEquals(pop.authority, popRetrieved.authority);
+ assertEquals(pop.expedited, popRetrieved.expedited);
+ assertEquals(pop.serviceName, popRetrieved.serviceName);
+ assert(android.content.PeriodicSync.syncExtrasEquals(pop.extras, popRetrieved.extras));
+
}
/**