summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/input/InputReader.cpp8
-rw-r--r--services/input/InputReader.h1
-rw-r--r--services/java/com/android/server/ConnectivityService.java32
-rw-r--r--services/java/com/android/server/InputMethodManagerService.java35
-rw-r--r--services/java/com/android/server/NotificationManagerService.java6
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java473
-rw-r--r--services/java/com/android/server/pm/Settings.java297
-rw-r--r--services/java/com/android/server/power/ElectronBeam.java3
-rw-r--r--services/java/com/android/server/wifi/README.txt12
-rw-r--r--services/java/com/android/server/wifi/WifiController.java626
-rw-r--r--services/java/com/android/server/wifi/WifiService.java318
-rw-r--r--services/java/com/android/server/wifi/WifiSettingsStore.java23
12 files changed, 1361 insertions, 473 deletions
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index bc8df18..43d76bb 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -2788,6 +2788,8 @@ void TouchInputMapper::configureParameters() {
mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
} else if (deviceTypeString == "touchPad") {
mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
+ } else if (deviceTypeString == "touchNavigation") {
+ mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION;
} else if (deviceTypeString == "pointer") {
mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
} else if (deviceTypeString != "default") {
@@ -2832,6 +2834,9 @@ void TouchInputMapper::dumpParameters(String8& dump) {
case Parameters::DEVICE_TYPE_TOUCH_PAD:
dump.append(INDENT4 "DeviceType: touchPad\n");
break;
+ case Parameters::DEVICE_TYPE_TOUCH_NAVIGATION:
+ dump.append(INDENT4 "DeviceType: touchNavigation\n");
+ break;
case Parameters::DEVICE_TYPE_POINTER:
dump.append(INDENT4 "DeviceType: pointer\n");
break;
@@ -2885,6 +2890,9 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
if (hasStylus()) {
mSource |= AINPUT_SOURCE_STYLUS;
}
+ } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) {
+ mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
+ mDeviceMode = DEVICE_MODE_UNSCALED;
} else {
mSource = AINPUT_SOURCE_TOUCHPAD;
mDeviceMode = DEVICE_MODE_UNSCALED;
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 61b21e2..c596b37 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -1192,6 +1192,7 @@ protected:
enum DeviceType {
DEVICE_TYPE_TOUCH_SCREEN,
DEVICE_TYPE_TOUCH_PAD,
+ DEVICE_TYPE_TOUCH_NAVIGATION,
DEVICE_TYPE_POINTER,
};
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 027f0f3..0b3df35 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -1413,11 +1413,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) {
- return modifyRoute(p.getInterfaceName(), p, r, 0, ADD, toDefaultTable);
+ return modifyRoute(p, r, 0, ADD, toDefaultTable);
}
private boolean removeRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) {
- return modifyRoute(p.getInterfaceName(), p, r, 0, REMOVE, toDefaultTable);
+ return modifyRoute(p, r, 0, REMOVE, toDefaultTable);
}
private boolean addRouteToAddress(LinkProperties lp, InetAddress addr) {
@@ -1430,11 +1430,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd,
boolean toDefaultTable) {
- String iface = lp.getInterfaceName();
- RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), addr);
+ RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getAllRoutes(), addr);
if (bestRoute == null) {
- bestRoute = RouteInfo.makeHostRoute(addr, iface);
+ bestRoute = RouteInfo.makeHostRoute(addr, lp.getInterfaceName());
} else {
+ String iface = bestRoute.getInterface();
if (bestRoute.getGateway().equals(addr)) {
// if there is no better route, add the implied hostroute for our gateway
bestRoute = RouteInfo.makeHostRoute(addr, iface);
@@ -1444,13 +1444,13 @@ public class ConnectivityService extends IConnectivityManager.Stub {
bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway(), iface);
}
}
- return modifyRoute(lp.getInterfaceName(), lp, bestRoute, 0, doAdd, toDefaultTable);
+ return modifyRoute(lp, bestRoute, 0, doAdd, toDefaultTable);
}
- private boolean modifyRoute(String ifaceName, LinkProperties lp, RouteInfo r, int cycleCount,
- boolean doAdd, boolean toDefaultTable) {
- if ((ifaceName == null) || (lp == null) || (r == null)) {
- if (DBG) log("modifyRoute got unexpected null: " + ifaceName + ", " + lp + ", " + r);
+ private boolean modifyRoute(LinkProperties lp, RouteInfo r, int cycleCount, boolean doAdd,
+ boolean toDefaultTable) {
+ if ((lp == null) || (r == null)) {
+ if (DBG) log("modifyRoute got unexpected null: " + lp + ", " + r);
return false;
}
@@ -1459,8 +1459,14 @@ public class ConnectivityService extends IConnectivityManager.Stub {
return false;
}
+ String ifaceName = r.getInterface();
+ if(ifaceName == null) {
+ loge("Error modifying route - no interface name");
+ return false;
+ }
+
if (r.isHostRoute() == false) {
- RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), r.getGateway());
+ RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getAllRoutes(), r.getGateway());
if (bestRoute != null) {
if (bestRoute.getGateway().equals(r.getGateway())) {
// if there is no better route, add the implied hostroute for our gateway
@@ -1472,7 +1478,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
bestRoute.getGateway(),
ifaceName);
}
- modifyRoute(ifaceName, lp, bestRoute, cycleCount+1, doAdd, toDefaultTable);
+ modifyRoute(lp, bestRoute, cycleCount+1, doAdd, toDefaultTable);
}
}
if (doAdd) {
@@ -2299,7 +2305,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
routeDiff = curLp.compareRoutes(newLp);
dnsDiff = curLp.compareDnses(newLp);
} else if (newLp != null) {
- routeDiff.added = newLp.getRoutes();
+ routeDiff.added = newLp.getAllRoutes();
dnsDiff.added = newLp.getDnses();
}
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 6ba5cff..14841af 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -1199,7 +1199,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mCurId = info.getId();
mCurToken = new Binder();
try {
- if (DEBUG) Slog.v(TAG, "Adding window token: " + mCurToken);
+ if (true || DEBUG) Slog.v(TAG, "Adding window token: " + mCurToken);
mIWindowManager.addWindowToken(mCurToken,
WindowManager.LayoutParams.TYPE_INPUT_METHOD);
} catch (RemoteException e) {
@@ -1237,13 +1237,24 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized (mMethodMap) {
if (mCurIntent != null && name.equals(mCurIntent.getComponent())) {
+ IInputMethod prevMethod = mCurMethod;
mCurMethod = IInputMethod.Stub.asInterface(service);
if (mCurToken == null) {
Slog.w(TAG, "Service connected without a token!");
unbindCurrentMethodLocked(false, false);
return;
}
- if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
+ // Remove messages relating to the previous service. Otherwise WindowManagerService
+ // will throw a BadTokenException because the old token is being removed.
+ if (prevMethod != null) {
+ try {
+ prevMethod.removeSoftInputMessages();
+ } catch (RemoteException e) {
+ }
+ }
+ mCaller.removeMessages(MSG_SHOW_SOFT_INPUT);
+ mCaller.removeMessages(MSG_HIDE_SOFT_INPUT);
+ if (true || DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
MSG_ATTACH_TOKEN, mCurMethod, mCurToken));
if (mCurClient != null) {
@@ -1689,7 +1700,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
}
- if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
+ if (true || DEBUG) Slog.v(TAG, "Client requesting input be shown");
return showCurrentInputLocked(flags, resultReceiver);
}
} finally {
@@ -1713,6 +1724,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
boolean res = false;
if (mCurMethod != null) {
+ if (true ||DEBUG) Slog.d(TAG, "showCurrentInputLocked: mCurToken=" + mCurToken,
+ new RuntimeException("here").fillInStackTrace());
executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(
MSG_SHOW_SOFT_INPUT, getImeShowFlags(), mCurMethod,
resultReceiver));
@@ -1784,12 +1797,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
boolean hideCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
if ((flags&InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
&& (mShowExplicitlyRequested || mShowForced)) {
- if (DEBUG) Slog.v(TAG,
+ if (true ||DEBUG) Slog.v(TAG,
"Not hiding: explicit show not cancelled by non-explicit hide");
return false;
}
if (mShowForced && (flags&InputMethodManager.HIDE_NOT_ALWAYS) != 0) {
- if (DEBUG) Slog.v(TAG,
+ if (true ||DEBUG) Slog.v(TAG,
"Not hiding: forced show not cancelled by not-always hide");
return false;
}
@@ -2301,8 +2314,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
case MSG_SHOW_SOFT_INPUT:
args = (SomeArgs)msg.obj;
try {
- ((IInputMethod)args.arg1).showSoftInput(msg.arg1,
- (ResultReceiver)args.arg2);
+ if (true || DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".showSoftInput("
+ + msg.arg1 + ", " + args.arg2 + ")");
+ ((IInputMethod)args.arg1).showSoftInput(msg.arg1, (ResultReceiver)args.arg2);
} catch (RemoteException e) {
}
args.recycle();
@@ -2310,8 +2324,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
case MSG_HIDE_SOFT_INPUT:
args = (SomeArgs)msg.obj;
try {
- ((IInputMethod)args.arg1).hideSoftInput(0,
- (ResultReceiver)args.arg2);
+ if (true || DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".hideSoftInput(0, "
+ + args.arg2 + ")");
+ ((IInputMethod)args.arg1).hideSoftInput(0, (ResultReceiver)args.arg2);
} catch (RemoteException e) {
}
args.recycle();
@@ -2319,7 +2334,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
case MSG_ATTACH_TOKEN:
args = (SomeArgs)msg.obj;
try {
- if (DEBUG) Slog.v(TAG, "Sending attach of token: " + args.arg2);
+ if (true || DEBUG) Slog.v(TAG, "Sending attach of token: " + args.arg2);
((IInputMethod)args.arg1).attachToken((IBinder)args.arg2);
} catch (RemoteException e) {
}
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 1e394d6..9e036d1 100644
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -1255,9 +1255,6 @@ public class NotificationManagerService extends INotificationManager.Stub
sendAccessibilityEvent(notification, pkg);
}
- // finally, keep some of this information around for later use
- mArchive.record(n);
-
notifyPostedLocked(r);
} else {
Slog.e(TAG, "Ignoring notification with icon==0: " + notification);
@@ -1472,6 +1469,9 @@ public class NotificationManagerService extends INotificationManager.Stub
if (mLedNotification == r) {
mLedNotification = null;
}
+
+ // Save it for users of getHistoricalNotifications()
+ mArchive.record(r.sbn);
}
/**
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 51f001f..2d12a77 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -170,7 +170,7 @@ adb shell am instrument -w -e class com.android.unit_tests.PackageManagerTests c
public class PackageManagerService extends IPackageManager.Stub {
static final String TAG = "PackageManager";
static final boolean DEBUG_SETTINGS = false;
- static final boolean DEBUG_PREFERRED = true;
+ static final boolean DEBUG_PREFERRED = false;
static final boolean DEBUG_UPGRADE = false;
private static final boolean DEBUG_INSTALL = false;
private static final boolean DEBUG_REMOVE = false;
@@ -339,9 +339,20 @@ public class PackageManagerService extends IPackageManager.Stub {
final SparseArray<HashSet<String>> mSystemPermissions =
new SparseArray<HashSet<String>>();
+ static final class SharedLibraryEntry {
+ final String path;
+ final String apk;
+
+ SharedLibraryEntry(String _path, String _apk) {
+ path = _path;
+ apk = _apk;
+ }
+ }
+
// These are the built-in shared libraries that were read from the
// etc/permissions.xml file.
- final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
+ final HashMap<String, SharedLibraryEntry> mSharedLibraries
+ = new HashMap<String, SharedLibraryEntry>();
// Temporary for building the final shared libraries for an .apk.
String[] mTmpSharedLibraries = null;
@@ -390,8 +401,7 @@ public class PackageManagerService extends IPackageManager.Stub {
final SparseArray<PackageVerificationState> mPendingVerification
= new SparseArray<PackageVerificationState>();
- final ArrayList<PackageParser.Package> mDeferredDexOpt =
- new ArrayList<PackageParser.Package>();
+ HashSet<PackageParser.Package> mDeferredDexOpt = null;
/** Token for keys in mPendingVerification. */
private int mPendingVerificationToken = 0;
@@ -514,10 +524,9 @@ public class PackageManagerService extends IPackageManager.Stub {
void doHandleMessage(Message msg) {
switch (msg.what) {
case INIT_COPY: {
- if (DEBUG_INSTALL) Slog.i(TAG, "init_copy");
HandlerParams params = (HandlerParams) msg.obj;
int idx = mPendingInstalls.size();
- if (DEBUG_INSTALL) Slog.i(TAG, "idx=" + idx);
+ if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
// If a bind was already initiated we dont really
// need to do anything. The pending install
// will be processed later on.
@@ -1071,9 +1080,12 @@ public class PackageManagerService extends IPackageManager.Stub {
* Also ensure all external libraries have had dexopt run on them.
*/
if (mSharedLibraries.size() > 0) {
- Iterator<String> libs = mSharedLibraries.values().iterator();
+ Iterator<SharedLibraryEntry> libs = mSharedLibraries.values().iterator();
while (libs.hasNext()) {
- String lib = libs.next();
+ String lib = libs.next().path;
+ if (lib == null) {
+ continue;
+ }
try {
if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
libFiles.add(lib);
@@ -1277,6 +1289,10 @@ public class PackageManagerService extends IPackageManager.Stub {
mDrmAppInstallObserver = null;
}
+ // Now that we know all of the shared libraries, update all clients to have
+ // the correct library paths.
+ updateAllSharedLibrariesLPw();
+
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
SystemClock.uptimeMillis());
Slog.i(TAG, "Time to scan packages: "
@@ -1517,7 +1533,7 @@ public class PackageManagerService extends IPackageManager.Stub {
+ parser.getPositionDescription());
} else {
//Log.i(TAG, "Got library " + lname + " in " + lfile);
- mSharedLibraries.put(lname, lfile);
+ mSharedLibraries.put(lname, new SharedLibraryEntry(lfile, null));
}
XmlUtils.skipCurrentTag(parser);
continue;
@@ -3249,6 +3265,7 @@ public class PackageManagerService extends IPackageManager.Stub {
int parseFlags, int scanMode, long currentTime, UserHandle user) {
mLastScanError = PackageManager.INSTALL_SUCCEEDED;
String scanPath = scanFile.getPath();
+ if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanPath);
parseFlags |= mDefParseFlags;
PackageParser pp = new PackageParser(scanPath);
pp.setSeparateProcesses(mSeparateProcesses);
@@ -3278,6 +3295,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// package. Must look for it either under the original or real
// package name depending on our state.
updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName);
+ if (DEBUG_INSTALL && updatedPkg != null) Slog.d(TAG, "updatedPkg = " + updatedPkg);
}
// First check if this is a system package that may involve an update
if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
@@ -3285,6 +3303,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// The path has changed from what was last scanned... check the
// version of the new path against what we have stored to determine
// what to do.
+ if (DEBUG_INSTALL) Slog.d(TAG, "Path changing from " + ps.codePath);
if (pkg.mVersionCode < ps.versionCode) {
// The system package has been updated and the code path does not match
// Ignore entry. Skip it.
@@ -3298,6 +3317,7 @@ public class PackageManagerService extends IPackageManager.Stub {
updatedPkg.codePath = scanFile;
updatedPkg.codePathString = scanFile.toString();
}
+ updatedPkg.pkg = pkg;
mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
return null;
} else {
@@ -3353,6 +3373,7 @@ public class PackageManagerService extends IPackageManager.Stub {
*/
if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures)
!= PackageManager.SIGNATURE_MATCH) {
+ if (DEBUG_INSTALL) Slog.d(TAG, "Signature mismatch!");
deletePackageLI(pkg.packageName, null, true, 0, null, false);
ps = null;
} else {
@@ -3484,28 +3505,28 @@ public class PackageManagerService extends IPackageManager.Stub {
}
public void performBootDexOpt() {
- ArrayList<PackageParser.Package> pkgs = null;
+ HashSet<PackageParser.Package> pkgs = null;
synchronized (mPackages) {
- if (mDeferredDexOpt.size() > 0) {
- pkgs = new ArrayList<PackageParser.Package>(mDeferredDexOpt);
- mDeferredDexOpt.clear();
- }
+ pkgs = mDeferredDexOpt;
+ mDeferredDexOpt = null;
}
if (pkgs != null) {
- for (int i=0; i<pkgs.size(); i++) {
+ int i = 0;
+ for (PackageParser.Package pkg : pkgs) {
if (!isFirstBoot()) {
+ i++;
try {
ActivityManagerNative.getDefault().showBootMessage(
mContext.getResources().getString(
com.android.internal.R.string.android_upgrading_apk,
- i+1, pkgs.size()), true);
+ i, pkgs.size()), true);
} catch (RemoteException e) {
}
}
- PackageParser.Package p = pkgs.get(i);
+ PackageParser.Package p = pkg;
synchronized (mInstallLock) {
if (!p.mDidDexOpt) {
- performDexOptLI(p, false, false);
+ performDexOptLI(p, false, false, true);
}
}
}
@@ -3527,7 +3548,27 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
synchronized (mInstallLock) {
- return performDexOptLI(p, false, false) == DEX_OPT_PERFORMED;
+ return performDexOptLI(p, false, false, true) == DEX_OPT_PERFORMED;
+ }
+ }
+
+ private void performDexOptLibsLI(ArrayList<String> libs, boolean forceDex, boolean defer,
+ HashSet<String> done) {
+ for (int i=0; i<libs.size(); i++) {
+ PackageParser.Package libPkg;
+ String libName;
+ synchronized (mPackages) {
+ libName = libs.get(i);
+ SharedLibraryEntry lib = mSharedLibraries.get(libName);
+ if (lib != null && lib.apk != null) {
+ libPkg = mPackages.get(lib.apk);
+ } else {
+ libPkg = null;
+ }
+ }
+ if (libPkg != null && !done.contains(libName)) {
+ performDexOptLI(libPkg, forceDex, defer, done);
+ }
}
}
@@ -3536,14 +3577,27 @@ public class PackageManagerService extends IPackageManager.Stub {
static final int DEX_OPT_DEFERRED = 2;
static final int DEX_OPT_FAILED = -1;
- private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer) {
+ private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer,
+ HashSet<String> done) {
boolean performed = false;
+ if (done != null) {
+ done.add(pkg.packageName);
+ if (pkg.usesLibraries != null) {
+ performDexOptLibsLI(pkg.usesLibraries, forceDex, defer, done);
+ }
+ if (pkg.usesOptionalLibraries != null) {
+ performDexOptLibsLI(pkg.usesOptionalLibraries, forceDex, defer, done);
+ }
+ }
if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
String path = pkg.mScanPath;
int ret = 0;
try {
if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
if (!forceDex && defer) {
+ if (mDeferredDexOpt == null) {
+ mDeferredDexOpt = new HashSet<PackageParser.Package>();
+ }
mDeferredDexOpt.add(pkg);
return DEX_OPT_DEFERRED;
} else {
@@ -3576,6 +3630,19 @@ public class PackageManagerService extends IPackageManager.Stub {
return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
}
+ private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer,
+ boolean inclDependencies) {
+ HashSet<String> done;
+ boolean performed = false;
+ if (inclDependencies && (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null)) {
+ done = new HashSet<String>();
+ done.add(pkg.packageName);
+ } else {
+ done = null;
+ }
+ return performDexOptLI(pkg, forceDex, defer, done);
+ }
+
private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) {
if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
Slog.w(TAG, "Unable to update from " + oldPkg.name
@@ -3646,6 +3713,113 @@ public class PackageManagerService extends IPackageManager.Stub {
return res;
}
+ private int addSharedLibraryLPw(final SharedLibraryEntry file, int num,
+ PackageParser.Package changingLib) {
+ if (file.path != null) {
+ mTmpSharedLibraries[num] = file.path;
+ return num+1;
+ }
+ PackageParser.Package p = mPackages.get(file.apk);
+ if (changingLib != null && changingLib.packageName.equals(file.apk)) {
+ // If we are doing this while in the middle of updating a library apk,
+ // then we need to make sure to use that new apk for determining the
+ // dependencies here. (We haven't yet finished committing the new apk
+ // to the package manager state.)
+ if (p == null || p.packageName.equals(changingLib.packageName)) {
+ p = changingLib;
+ }
+ }
+ if (p != null) {
+ String path = p.mPath;
+ for (int i=0; i<num; i++) {
+ if (mTmpSharedLibraries[i].equals(path)) {
+ return num;
+ }
+ }
+ mTmpSharedLibraries[num] = p.mPath;
+ return num+1;
+ }
+ return num;
+ }
+
+ private boolean updateSharedLibrariesLPw(PackageParser.Package pkg,
+ PackageParser.Package changingLib) {
+ if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
+ if (mTmpSharedLibraries == null ||
+ mTmpSharedLibraries.length < mSharedLibraries.size()) {
+ mTmpSharedLibraries = new String[mSharedLibraries.size()];
+ }
+ int num = 0;
+ int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
+ for (int i=0; i<N; i++) {
+ final SharedLibraryEntry file = mSharedLibraries.get(pkg.usesLibraries.get(i));
+ if (file == null) {
+ Slog.e(TAG, "Package " + pkg.packageName
+ + " requires unavailable shared library "
+ + pkg.usesLibraries.get(i) + "; failing!");
+ mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
+ return false;
+ }
+ num = addSharedLibraryLPw(file, num, changingLib);
+ }
+ N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
+ for (int i=0; i<N; i++) {
+ final SharedLibraryEntry file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
+ if (file == null) {
+ Slog.w(TAG, "Package " + pkg.packageName
+ + " desires unavailable shared library "
+ + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
+ } else {
+ num = addSharedLibraryLPw(file, num, changingLib);
+ }
+ }
+ if (num > 0) {
+ pkg.usesLibraryFiles = new String[num];
+ System.arraycopy(mTmpSharedLibraries, 0,
+ pkg.usesLibraryFiles, 0, num);
+ } else {
+ pkg.usesLibraryFiles = null;
+ }
+ }
+ return true;
+ }
+
+ private static boolean hasString(List<String> list, List<String> which) {
+ if (list == null) {
+ return false;
+ }
+ for (int i=list.size()-1; i>=0; i--) {
+ for (int j=which.size()-1; j>=0; j--) {
+ if (which.get(j).equals(list.get(i))) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private void updateAllSharedLibrariesLPw() {
+ for (PackageParser.Package pkg : mPackages.values()) {
+ updateSharedLibrariesLPw(pkg, null);
+ }
+ }
+
+ private ArrayList<PackageParser.Package> updateAllSharedLibrariesLPw(
+ PackageParser.Package changingPkg) {
+ ArrayList<PackageParser.Package> res = null;
+ for (PackageParser.Package pkg : mPackages.values()) {
+ if (hasString(pkg.usesLibraries, changingPkg.libraryNames)
+ || hasString(pkg.usesOptionalLibraries, changingPkg.libraryNames)) {
+ if (res == null) {
+ res = new ArrayList<PackageParser.Package>();
+ }
+ res.add(pkg);
+ updateSharedLibrariesLPw(pkg, changingPkg);
+ }
+ }
+ return res;
+ }
+
private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
int parseFlags, int scanMode, long currentTime, UserHandle user) {
File scanFile = new File(pkg.mScanPath);
@@ -3725,42 +3899,14 @@ public class PackageManagerService extends IPackageManager.Stub {
// writer
synchronized (mPackages) {
- // Check all shared libraries and map to their actual file path.
- if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
- if (mTmpSharedLibraries == null ||
- mTmpSharedLibraries.length < mSharedLibraries.size()) {
- mTmpSharedLibraries = new String[mSharedLibraries.size()];
- }
- int num = 0;
- int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
- for (int i=0; i<N; i++) {
- final String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
- if (file == null) {
- Slog.e(TAG, "Package " + pkg.packageName
- + " requires unavailable shared library "
- + pkg.usesLibraries.get(i) + "; failing!");
- mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
- return null;
- }
- mTmpSharedLibraries[num] = file;
- num++;
- }
- N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
- for (int i=0; i<N; i++) {
- final String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
- if (file == null) {
- Slog.w(TAG, "Package " + pkg.packageName
- + " desires unavailable shared library "
- + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
- } else {
- mTmpSharedLibraries[num] = file;
- num++;
- }
- }
- if (num > 0) {
- pkg.usesLibraryFiles = new String[num];
- System.arraycopy(mTmpSharedLibraries, 0,
- pkg.usesLibraryFiles, 0, num);
+ if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+ // Check all shared libraries and map to their actual file path.
+ // We only do this here for apps not on a system dir, because those
+ // are the only ones that can fail an install due to this. We
+ // will take care of the system apps by updating all of their
+ // library paths after the scan is done.
+ if (!updateSharedLibrariesLPw(pkg, null)) {
+ return null;
}
}
@@ -4166,7 +4312,7 @@ public class PackageManagerService extends IPackageManager.Stub {
pkg.mScanPath = path;
if ((scanMode&SCAN_NO_DEX) == 0) {
- if (performDexOptLI(pkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0)
+ if (performDexOptLI(pkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false)
== DEX_OPT_FAILED) {
mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
return null;
@@ -4178,6 +4324,80 @@ public class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
}
+ ArrayList<PackageParser.Package> clientLibPkgs = null;
+
+ // writer
+ synchronized (mPackages) {
+ if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
+ // Only system apps can add new shared libraries.
+ if (pkg.libraryNames != null) {
+ for (int i=0; i<pkg.libraryNames.size(); i++) {
+ String name = pkg.libraryNames.get(i);
+ boolean allowed = false;
+ if (isUpdatedSystemApp(pkg)) {
+ // New library entries can only be added through the
+ // system image. This is important to get rid of a lot
+ // of nasty edge cases: for example if we allowed a non-
+ // system update of the app to add a library, then uninstalling
+ // the update would make the library go away, and assumptions
+ // we made such as through app install filtering would now
+ // have allowed apps on the device which aren't compatible
+ // with it. Better to just have the restriction here, be
+ // conservative, and create many fewer cases that can negatively
+ // impact the user experience.
+ final PackageSetting sysPs = mSettings
+ .getDisabledSystemPkgLPr(pkg.packageName);
+ if (sysPs.pkg != null && sysPs.pkg.libraryNames != null) {
+ for (int j=0; j<sysPs.pkg.libraryNames.size(); j++) {
+ if (name.equals(sysPs.pkg.libraryNames.get(j))) {
+ allowed = true;
+ allowed = true;
+ break;
+ }
+ }
+ }
+ } else {
+ allowed = true;
+ }
+ if (allowed) {
+ if (!mSharedLibraries.containsKey(name)) {
+ mSharedLibraries.put(name, new SharedLibraryEntry(null,
+ pkg.packageName));
+ } else if (!name.equals(pkg.packageName)) {
+ Slog.w(TAG, "Package " + pkg.packageName + " library "
+ + name + " already exists; skipping");
+ }
+ } else {
+ Slog.w(TAG, "Package " + pkg.packageName + " declares lib "
+ + name + " that is not declared on system image; skipping");
+ }
+ }
+ if ((scanMode&SCAN_BOOTING) == 0) {
+ // If we are not booting, we need to update any applications
+ // that are clients of our shared library. If we are booting,
+ // this will all be done once the scan is complete.
+ clientLibPkgs = updateAllSharedLibrariesLPw(pkg);
+ }
+ }
+ }
+ }
+
+ // We also need to dexopt any apps that are dependent on this library. Note that
+ // if these fail, we should abort the install since installing the library will
+ // result in some apps being broken.
+ if (clientLibPkgs != null) {
+ if ((scanMode&SCAN_NO_DEX) == 0) {
+ for (int i=0; i<clientLibPkgs.size(); i++) {
+ PackageParser.Package clientPkg = clientLibPkgs.get(i);
+ if (performDexOptLI(clientPkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false)
+ == DEX_OPT_FAILED) {
+ mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
+ return null;
+ }
+ }
+ }
+ }
+
// Request the ActivityManager to kill the process(only for existing packages)
// so that we do not end up in a confused state while the user is still using the older
// version of the application while the new one gets installed.
@@ -4186,6 +4406,15 @@ public class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.uid);
}
+ // Also need to kill any apps that are dependent on the library.
+ if (clientLibPkgs != null) {
+ for (int i=0; i<clientLibPkgs.size(); i++) {
+ PackageParser.Package clientPkg = clientLibPkgs.get(i);
+ killApplication(clientPkg.applicationInfo.packageName,
+ clientPkg.applicationInfo.uid);
+ }
+ }
+
// writer
synchronized (mPackages) {
// We don't expect installation to fail beyond this point,
@@ -4591,7 +4820,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
}
- if (chatty) {
+ if (DEBUG_REMOVE && chatty) {
if (r == null) {
r = new StringBuilder(256);
} else {
@@ -4627,7 +4856,7 @@ public class PackageManagerService extends IPackageManager.Stub {
for (i=0; i<N; i++) {
PackageParser.Activity a = pkg.receivers.get(i);
mReceivers.removeActivity(a, "receiver");
- if (chatty) {
+ if (DEBUG_REMOVE && chatty) {
if (r == null) {
r = new StringBuilder(256);
} else {
@@ -4645,7 +4874,7 @@ public class PackageManagerService extends IPackageManager.Stub {
for (i=0; i<N; i++) {
PackageParser.Activity a = pkg.activities.get(i);
mActivities.removeActivity(a, "activity");
- if (chatty) {
+ if (DEBUG_REMOVE && chatty) {
if (r == null) {
r = new StringBuilder(256);
} else {
@@ -4668,7 +4897,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
if (bp != null && bp.perm == p) {
bp.perm = null;
- if (chatty) {
+ if (DEBUG_REMOVE && chatty) {
if (r == null) {
r = new StringBuilder(256);
} else {
@@ -4687,7 +4916,7 @@ public class PackageManagerService extends IPackageManager.Stub {
for (i=0; i<N; i++) {
PackageParser.Instrumentation a = pkg.instrumentation.get(i);
mInstrumentation.remove(a.getComponentName());
- if (chatty) {
+ if (DEBUG_REMOVE && chatty) {
if (r == null) {
r = new StringBuilder(256);
} else {
@@ -4699,6 +4928,31 @@ public class PackageManagerService extends IPackageManager.Stub {
if (r != null) {
if (DEBUG_REMOVE) Log.d(TAG, " Instrumentation: " + r);
}
+
+ r = null;
+ if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
+ // Only system apps can hold shared libraries.
+ if (pkg.libraryNames != null) {
+ for (i=0; i<pkg.libraryNames.size(); i++) {
+ String name = pkg.libraryNames.get(i);
+ SharedLibraryEntry cur = mSharedLibraries.get(name);
+ if (cur != null && cur.apk != null && cur.apk.equals(pkg.packageName)) {
+ mSharedLibraries.remove(name);
+ if (DEBUG_REMOVE && chatty) {
+ if (r == null) {
+ r = new StringBuilder(256);
+ } else {
+ r.append(' ');
+ }
+ r.append(name);
+ }
+ }
+ }
+ }
+ }
+ if (r != null) {
+ if (DEBUG_REMOVE) Log.d(TAG, " Libraries: " + r);
+ }
}
private static final boolean isPackageFilename(String name) {
@@ -4860,7 +5114,23 @@ public class PackageManagerService extends IPackageManager.Stub {
if (origGp.grantedPermissions.contains(perm)) {
allowed = true;
} else {
+ // The system apk may have been updated with an older
+ // version of the one on the data partition, but which
+ // granted a new system permission that it didn't have
+ // before. In this case we do want to allow the app to
+ // now get the new permission, because it is allowed by
+ // the system image.
allowed = false;
+ if (sysPs.pkg != null) {
+ for (int j=0;
+ j<sysPs.pkg.requestedPermissions.size(); j++) {
+ if (perm.equals(
+ sysPs.pkg.requestedPermissions.get(j))) {
+ allowed = true;
+ break;
+ }
+ }
+ }
}
} else {
allowed = true;
@@ -5557,6 +5827,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
if ((event&REMOVE_EVENTS) != 0) {
if (ps != null) {
+ if (DEBUG_REMOVE) Slog.d(TAG, "Package disappeared: " + ps);
removePackageLI(ps, true);
removedPackage = ps.name;
removedAppId = ps.appId;
@@ -5565,6 +5836,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if ((event&ADD_EVENTS) != 0) {
if (p == null) {
+ if (DEBUG_INSTALL) Slog.d(TAG, "New file appeared: " + fullPath);
p = scanPackageLI(fullPath,
(mIsRom ? PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR: 0) |
@@ -6126,7 +6398,7 @@ public class PackageManagerService extends IPackageManager.Stub {
final boolean startCopy() {
boolean res;
try {
- if (DEBUG_INSTALL) Slog.i(TAG, "startCopy");
+ if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
if (++mRetries > MAX_RETRIES) {
Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
@@ -6170,6 +6442,13 @@ public class PackageManagerService extends IPackageManager.Stub {
}
@Override
+ public String toString() {
+ return "MeasureParams{"
+ + Integer.toHexString(System.identityHashCode(this))
+ + " " + mStats.packageName + "}";
+ }
+
+ @Override
void handleStartCopy() throws RemoteException {
synchronized (mInstallLock) {
mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats.userHandle, mStats);
@@ -6258,6 +6537,13 @@ public class PackageManagerService extends IPackageManager.Stub {
this.encryptionParams = encryptionParams;
}
+ @Override
+ public String toString() {
+ return "InstallParams{"
+ + Integer.toHexString(System.identityHashCode(this))
+ + " " + mPackageURI + "}";
+ }
+
public ManifestDigest getManifestDigest() {
if (verificationParams == null) {
return null;
@@ -6671,6 +6957,13 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+ @Override
+ public String toString() {
+ return "MoveParams{"
+ + Integer.toHexString(System.identityHashCode(this))
+ + " " + packageName + "}";
+ }
+
public void handleStartCopy() throws RemoteException {
mRet = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
// Check for storage space on target medium
@@ -7582,6 +7875,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Remember this for later, in case we need to rollback this install
String pkgName = pkg.packageName;
+ if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);
boolean dataDirExists = getDataPathForPackage(pkg.packageName, 0).exists();
synchronized(mPackages) {
if (mSettings.mRenamedPackages.containsKey(pkgName)) {
@@ -7638,6 +7932,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// First find the old package info and check signatures
synchronized(mPackages) {
oldPackage = mPackages.get(pkgName);
+ if (DEBUG_INSTALL) Slog.d(TAG, "replacePackageLI: new=" + pkg + ", old=" + oldPackage);
if (compareSignatures(oldPackage.mSignatures, pkg.mSignatures)
!= PackageManager.SIGNATURE_MATCH) {
Slog.w(TAG, "New package has a different signature: " + pkgName);
@@ -7663,6 +7958,8 @@ public class PackageManagerService extends IPackageManager.Stub {
boolean deletedPkg = true;
boolean updatedSettings = false;
+ if (DEBUG_INSTALL) Slog.d(TAG, "replaceNonSystemPackageLI: new=" + pkg + ", old="
+ + deletedPackage);
long origUpdateTime;
if (pkg.mExtras != null) {
origUpdateTime = ((PackageSetting)pkg.mExtras).lastUpdateTime;
@@ -7700,6 +7997,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// scanPackageLocked, unless those directories existed before we even tried to
// install.
if(updatedSettings) {
+ if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, rolling pack: " + pkgName);
deletePackageLI(
pkgName, null, true,
PackageManager.DELETE_KEEP_DATA,
@@ -7708,6 +8006,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Since we failed to install the new package we need to restore the old
// package that we deleted.
if(deletedPkg) {
+ if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, reinstalling: " + deletedPackage);
File restoreFile = new File(deletedPackage.mPath);
// Parse old package
boolean oldOnSd = isExternal(deletedPackage);
@@ -7737,6 +8036,8 @@ public class PackageManagerService extends IPackageManager.Stub {
private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
String installerPackageName, PackageInstalledInfo res) {
+ if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
+ + ", old=" + deletedPackage);
PackageParser.Package newPackage = null;
boolean updatedSettings = false;
parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
@@ -7859,7 +8160,7 @@ public class PackageManagerService extends IPackageManager.Stub {
return;
}
- Log.d(TAG, "New package installed in " + newPackage.mPath);
+ if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + newPackage.mPath);
synchronized (mPackages) {
updatePermissionsLPw(newPackage.packageName, newPackage,
@@ -7889,6 +8190,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Result object to be returned
res.returnCode = PackageManager.INSTALL_SUCCEEDED;
+ if (DEBUG_INSTALL) Slog.d(TAG, "installPackageLI: path=" + tmpPackageFile);
// Retrieve PackageSettings and parse package
int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
| (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)
@@ -7950,14 +8252,18 @@ public class PackageManagerService extends IPackageManager.Stub {
pkg.setPackageName(oldName);
pkgName = pkg.packageName;
replace = true;
+ if (DEBUG_INSTALL) Slog.d(TAG, "Replacing existing renamed package: oldName="
+ + oldName + " pkgName=" + pkgName);
} else if (mPackages.containsKey(pkgName)) {
// This package, under its official name, already exists
// on the device; we should replace it.
replace = true;
+ if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing pacakge: " + pkgName);
}
}
PackageSetting ps = mSettings.mPackages.get(pkgName);
if (ps != null) {
+ if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);
oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
if (ps.pkg != null && ps.pkg.applicationInfo != null) {
systemApp = (ps.pkg.applicationInfo.flags &
@@ -8104,6 +8410,7 @@ public class PackageManagerService extends IPackageManager.Stub {
return;
}
+ if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageAsUser: pkg=" + packageName + " user=" + userId);
// Queue up an async operation since the package deletion may take a little while.
mHandler.post(new Runnable() {
public void run() {
@@ -8151,6 +8458,7 @@ public class PackageManagerService extends IPackageManager.Stub {
boolean removedForAllUsers = false;
boolean systemUpdate = false;
synchronized (mInstallLock) {
+ if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId);
res = deletePackageLI(packageName,
(flags & PackageManager.DELETE_ALL_USERS) != 0
? UserHandle.ALL : new UserHandle(userId),
@@ -8159,6 +8467,8 @@ public class PackageManagerService extends IPackageManager.Stub {
if (res && !systemUpdate && mPackages.get(packageName) == null) {
removedForAllUsers = true;
}
+ if (DEBUG_REMOVE) Slog.d(TAG, "delete res: systemUpdate=" + systemUpdate
+ + " removedForAllUsers=" + removedForAllUsers);
}
if (res) {
@@ -8234,6 +8544,7 @@ public class PackageManagerService extends IPackageManager.Stub {
private void removePackageDataLI(PackageSetting ps, PackageRemovedInfo outInfo,
int flags, boolean writeSettings) {
String packageName = ps.name;
+ if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + ps);
removePackageLI(ps, (flags&REMOVE_CHATTY) != 0);
// Retrieve object to delete permissions for shared user later on
final PackageSetting deletedPs;
@@ -8289,11 +8600,13 @@ public class PackageManagerService extends IPackageManager.Stub {
synchronized (mPackages) {
disabledPs = mSettings.getDisabledSystemPkgLPr(newPs.name);
}
+ if (DEBUG_REMOVE) Slog.d(TAG, "deleteSystemPackageLI: newPs=" + newPs
+ + " disabledPs=" + disabledPs);
if (disabledPs == null) {
Slog.w(TAG, "Attempt to delete unknown system package "+ newPs.name);
return false;
- } else {
- Log.i(TAG, "Deleting system pkg from data partition");
+ } else if (DEBUG_REMOVE) {
+ Slog.d(TAG, "Deleting system pkg from data partition");
}
// Delete the updated package
outInfo.isRemovedPackageSystemUpdate = true;
@@ -8317,6 +8630,7 @@ public class PackageManagerService extends IPackageManager.Stub {
NativeLibraryHelper.removeNativeBinariesLI(newPs.nativeLibraryPathString);
}
// Install the system package
+ if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs);
PackageParser.Package newPkg = scanPackageLI(disabledPs.codePath,
PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
SCAN_MONITOR | SCAN_NO_PATHS, 0, null);
@@ -8366,6 +8680,7 @@ public class PackageManagerService extends IPackageManager.Stub {
Slog.w(TAG, "Attempt to delete null packageName.");
return false;
}
+ if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageLI: " + packageName + " user " + user);
PackageSetting ps;
boolean dataOnly = false;
int removeUser = -1;
@@ -8376,11 +8691,14 @@ public class PackageManagerService extends IPackageManager.Stub {
Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
return false;
}
- if (user != null
+ if ((!isSystemApp(ps) || (flags&PackageManager.DELETE_SYSTEM_APP) != 0) && user != null
&& user.getIdentifier() != UserHandle.USER_ALL) {
// The caller is asking that the package only be deleted for a single
// user. To do this, we just mark its uninstalled state and delete
- // its data.
+ // its data. If this is a system app, we only allow this to happen if
+ // they have set the special DELETE_SYSTEM_APP which requests different
+ // semantics than normal for uninstalling system apps.
+ if (DEBUG_REMOVE) Slog.d(TAG, "Only deleting for single user");
ps.setUserState(user.getIdentifier(),
COMPONENT_ENABLED_STATE_DEFAULT,
false, //installed
@@ -8392,12 +8710,14 @@ public class PackageManagerService extends IPackageManager.Stub {
// Other user still have this package installed, so all
// we need to do is clear this user's data and save that
// it is uninstalled.
+ if (DEBUG_REMOVE) Slog.d(TAG, "Still installed by other users");
removeUser = user.getIdentifier();
appId = ps.appId;
mSettings.writePackageRestrictionsLPr(removeUser);
} else {
// We need to set it back to 'installed' so the uninstall
// broadcasts will be sent correctly.
+ if (DEBUG_REMOVE) Slog.d(TAG, "Not installed by other users, full delete");
ps.setInstalled(true, user.getIdentifier());
}
} else {
@@ -8405,6 +8725,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// other users still have this package installed, so all
// we need to do is clear this user's data and save that
// it is uninstalled.
+ if (DEBUG_REMOVE) Slog.d(TAG, "Deleting system app");
removeUser = user.getIdentifier();
appId = ps.appId;
mSettings.writePackageRestrictionsLPr(removeUser);
@@ -8415,6 +8736,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (removeUser >= 0) {
// From above, we determined that we are deleting this only
// for a single user. Continue the work here.
+ if (DEBUG_REMOVE) Slog.d(TAG, "Updating install state for user: " + removeUser);
if (outInfo != null) {
outInfo.removedPackage = packageName;
outInfo.removedAppId = appId;
@@ -8427,17 +8749,18 @@ public class PackageManagerService extends IPackageManager.Stub {
if (dataOnly) {
// Delete application data first
+ if (DEBUG_REMOVE) Slog.d(TAG, "Removing package data only");
removePackageDataLI(ps, outInfo, flags, writeSettings);
return true;
}
boolean ret = false;
if (isSystemApp(ps)) {
- Log.i(TAG, "Removing system package:" + ps.name);
+ if (DEBUG_REMOVE) Slog.d(TAG, "Removing system package:" + ps.name);
// When an updated system application is deleted we delete the existing resources as well and
// fall back to existing code in system partition
ret = deleteSystemPackageLI(ps, flags, outInfo, writeSettings);
} else {
- Log.i(TAG, "Removing non-system package:" + ps.name);
+ if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package:" + ps.name);
// Kill application pre-emptively especially for apps on sd.
killApplication(packageName, ps.appId);
ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags, outInfo,
@@ -9408,7 +9731,15 @@ public class PackageManagerService extends IPackageManager.Stub {
pw.print(" ");
pw.print(name);
pw.print(" -> ");
- pw.println(mSharedLibraries.get(name));
+ SharedLibraryEntry ent = mSharedLibraries.get(name);
+ if (ent.path != null) {
+ pw.print("(jar) ");
+ pw.print(ent.path);
+ } else {
+ pw.print("(apk) ");
+ pw.print(ent.apk);
+ }
+ pw.println();
}
}
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 13f514b..e645078 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -32,7 +32,6 @@ import android.util.LogPrinter;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
import com.android.internal.util.XmlUtils;
-import com.android.server.IntentResolver;
import com.android.server.pm.PackageManagerService.DumpState;
import org.xmlpull.v1.XmlPullParser;
@@ -2657,6 +2656,162 @@ final class Settings {
ApplicationInfo.FLAG_CANT_SAVE_STATE, "CANT_SAVE_STATE",
};
+ void dumpPackageLPr(PrintWriter pw, String prefix, PackageSetting ps, SimpleDateFormat sdf,
+ Date date, List<UserInfo> users) {
+ pw.print(prefix); pw.print("Package [");
+ pw.print(ps.realName != null ? ps.realName : ps.name);
+ pw.print("] (");
+ pw.print(Integer.toHexString(System.identityHashCode(ps)));
+ pw.println("):");
+
+ if (ps.realName != null) {
+ pw.print(prefix); pw.print(" compat name=");
+ pw.println(ps.name);
+ }
+
+ pw.print(prefix); pw.print(" userId="); pw.print(ps.appId);
+ pw.print(" gids="); pw.println(PackageManagerService.arrayToString(ps.gids));
+ if (ps.sharedUser != null) {
+ pw.print(prefix); pw.print(" sharedUser="); pw.println(ps.sharedUser);
+ }
+ pw.print(prefix); pw.print(" pkg="); pw.println(ps.pkg);
+ pw.print(prefix); pw.print(" codePath="); pw.println(ps.codePathString);
+ pw.print(prefix); pw.print(" resourcePath="); pw.println(ps.resourcePathString);
+ pw.print(prefix); pw.print(" nativeLibraryPath="); pw.println(ps.nativeLibraryPathString);
+ pw.print(prefix); pw.print(" versionCode="); pw.print(ps.versionCode);
+ if (ps.pkg != null) {
+ pw.print(" targetSdk="); pw.print(ps.pkg.applicationInfo.targetSdkVersion);
+ }
+ pw.println();
+ if (ps.pkg != null) {
+ pw.print(prefix); pw.print(" versionName="); pw.println(ps.pkg.mVersionName);
+ pw.print(prefix); pw.print(" applicationInfo=");
+ pw.println(ps.pkg.applicationInfo.toString());
+ pw.print(prefix); pw.print(" flags="); printFlags(pw, ps.pkg.applicationInfo.flags,
+ FLAG_DUMP_SPEC); pw.println();
+ pw.print(prefix); pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
+ if (ps.pkg.mOperationPending) {
+ pw.print(prefix); pw.println(" mOperationPending=true");
+ }
+ pw.print(prefix); pw.print(" supportsScreens=[");
+ boolean first = true;
+ if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
+ if (!first)
+ pw.print(", ");
+ first = false;
+ pw.print("small");
+ }
+ if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
+ if (!first)
+ pw.print(", ");
+ first = false;
+ pw.print("medium");
+ }
+ if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
+ if (!first)
+ pw.print(", ");
+ first = false;
+ pw.print("large");
+ }
+ if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) {
+ if (!first)
+ pw.print(", ");
+ first = false;
+ pw.print("xlarge");
+ }
+ if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
+ if (!first)
+ pw.print(", ");
+ first = false;
+ pw.print("resizeable");
+ }
+ if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
+ if (!first)
+ pw.print(", ");
+ first = false;
+ pw.print("anyDensity");
+ }
+ pw.println("]");
+ if (ps.pkg.libraryNames != null && ps.pkg.libraryNames.size() > 0) {
+ pw.print(prefix); pw.println(" libraries:");
+ for (int i=0; i<ps.pkg.libraryNames.size(); i++) {
+ pw.print(prefix); pw.print(" "); pw.println(ps.pkg.libraryNames.get(i));
+ }
+ }
+ if (ps.pkg.usesLibraries != null && ps.pkg.usesLibraries.size() > 0) {
+ pw.print(prefix); pw.println(" usesLibraries:");
+ for (int i=0; i<ps.pkg.usesLibraries.size(); i++) {
+ pw.print(prefix); pw.print(" "); pw.println(ps.pkg.usesLibraries.get(i));
+ }
+ }
+ if (ps.pkg.usesOptionalLibraries != null
+ && ps.pkg.usesOptionalLibraries.size() > 0) {
+ pw.print(prefix); pw.println(" usesOptionalLibraries:");
+ for (int i=0; i<ps.pkg.usesOptionalLibraries.size(); i++) {
+ pw.print(prefix); pw.print(" ");
+ pw.println(ps.pkg.usesOptionalLibraries.get(i));
+ }
+ }
+ if (ps.pkg.usesLibraryFiles != null
+ && ps.pkg.usesLibraryFiles.length > 0) {
+ pw.print(prefix); pw.println(" usesLibraryFiles:");
+ for (int i=0; i<ps.pkg.usesLibraryFiles.length; i++) {
+ pw.print(prefix); pw.print(" "); pw.println(ps.pkg.usesLibraryFiles[i]);
+ }
+ }
+ }
+ pw.print(prefix); pw.print(" timeStamp=");
+ date.setTime(ps.timeStamp);
+ pw.println(sdf.format(date));
+ pw.print(prefix); pw.print(" firstInstallTime=");
+ date.setTime(ps.firstInstallTime);
+ pw.println(sdf.format(date));
+ pw.print(prefix); pw.print(" lastUpdateTime=");
+ date.setTime(ps.lastUpdateTime);
+ pw.println(sdf.format(date));
+ if (ps.installerPackageName != null) {
+ pw.print(prefix); pw.print(" installerPackageName=");
+ pw.println(ps.installerPackageName);
+ }
+ pw.print(prefix); pw.print(" signatures="); pw.println(ps.signatures);
+ pw.print(prefix); pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
+ pw.print(" haveGids="); pw.print(ps.haveGids);
+ pw.print(" installStatus="); pw.println(ps.installStatus);
+ pw.print(prefix); pw.print(" pkgFlags="); printFlags(pw, ps.pkgFlags, FLAG_DUMP_SPEC);
+ pw.println();
+ for (UserInfo user : users) {
+ pw.print(prefix); pw.print(" User "); pw.print(user.id); pw.print(": ");
+ pw.print(" installed=");
+ pw.print(ps.getInstalled(user.id));
+ pw.print(" stopped=");
+ pw.print(ps.getStopped(user.id));
+ pw.print(" notLaunched=");
+ pw.print(ps.getNotLaunched(user.id));
+ pw.print(" enabled=");
+ pw.println(ps.getEnabled(user.id));
+ HashSet<String> cmp = ps.getDisabledComponents(user.id);
+ if (cmp != null && cmp.size() > 0) {
+ pw.print(prefix); pw.println(" disabledComponents:");
+ for (String s : cmp) {
+ pw.print(prefix); pw.print(" "); pw.println(s);
+ }
+ }
+ cmp = ps.getEnabledComponents(user.id);
+ if (cmp != null && cmp.size() > 0) {
+ pw.print(prefix); pw.println(" enabledComponents:");
+ for (String s : cmp) {
+ pw.print(prefix); pw.print(" "); pw.println(s);
+ }
+ }
+ }
+ if (ps.grantedPermissions.size() > 0) {
+ pw.print(prefix); pw.println(" grantedPermissions:");
+ for (String s : ps.grantedPermissions) {
+ pw.print(prefix); pw.print(" "); pw.println(s);
+ }
+ }
+ }
+
void dumpPackagesLPr(PrintWriter pw, String packageName, DumpState dumpState) {
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
final Date date = new Date();
@@ -2678,123 +2833,7 @@ final class Settings {
pw.println("Packages:");
printedSomething = true;
}
- pw.print(" Package [");
- pw.print(ps.realName != null ? ps.realName : ps.name);
- pw.print("] (");
- pw.print(Integer.toHexString(System.identityHashCode(ps)));
- pw.println("):");
-
- if (ps.realName != null) {
- pw.print(" compat name=");
- pw.println(ps.name);
- }
-
- pw.print(" userId="); pw.print(ps.appId);
- pw.print(" gids="); pw.println(PackageManagerService.arrayToString(ps.gids));
- pw.print(" sharedUser="); pw.println(ps.sharedUser);
- pw.print(" pkg="); pw.println(ps.pkg);
- pw.print(" codePath="); pw.println(ps.codePathString);
- pw.print(" resourcePath="); pw.println(ps.resourcePathString);
- pw.print(" nativeLibraryPath="); pw.println(ps.nativeLibraryPathString);
- pw.print(" versionCode="); pw.println(ps.versionCode);
- if (ps.pkg != null) {
- pw.print(" applicationInfo="); pw.println(ps.pkg.applicationInfo.toString());
- pw.print(" flags="); printFlags(pw, ps.pkg.applicationInfo.flags, FLAG_DUMP_SPEC); pw.println();
- pw.print(" versionName="); pw.println(ps.pkg.mVersionName);
- pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
- pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
- if (ps.pkg.mOperationPending) {
- pw.println(" mOperationPending=true");
- }
- pw.print(" supportsScreens=[");
- boolean first = true;
- if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
- if (!first)
- pw.print(", ");
- first = false;
- pw.print("small");
- }
- if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
- if (!first)
- pw.print(", ");
- first = false;
- pw.print("medium");
- }
- if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
- if (!first)
- pw.print(", ");
- first = false;
- pw.print("large");
- }
- if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) {
- if (!first)
- pw.print(", ");
- first = false;
- pw.print("xlarge");
- }
- if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
- if (!first)
- pw.print(", ");
- first = false;
- pw.print("resizeable");
- }
- if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
- if (!first)
- pw.print(", ");
- first = false;
- pw.print("anyDensity");
- }
- pw.println("]");
- }
- pw.print(" timeStamp=");
- date.setTime(ps.timeStamp);
- pw.println(sdf.format(date));
- pw.print(" firstInstallTime=");
- date.setTime(ps.firstInstallTime);
- pw.println(sdf.format(date));
- pw.print(" lastUpdateTime=");
- date.setTime(ps.lastUpdateTime);
- pw.println(sdf.format(date));
- if (ps.installerPackageName != null) {
- pw.print(" installerPackageName="); pw.println(ps.installerPackageName);
- }
- pw.print(" signatures="); pw.println(ps.signatures);
- pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
- pw.print(" haveGids="); pw.print(ps.haveGids);
- pw.print(" installStatus="); pw.println(ps.installStatus);
- pw.print(" pkgFlags="); printFlags(pw, ps.pkgFlags, FLAG_DUMP_SPEC);
- pw.println();
- for (UserInfo user : users) {
- pw.print(" User "); pw.print(user.id); pw.print(": ");
- pw.print(" installed=");
- pw.print(ps.getInstalled(user.id));
- pw.print(" stopped=");
- pw.print(ps.getStopped(user.id));
- pw.print(" notLaunched=");
- pw.print(ps.getNotLaunched(user.id));
- pw.print(" enabled=");
- pw.println(ps.getEnabled(user.id));
- HashSet<String> cmp = ps.getDisabledComponents(user.id);
- if (cmp != null && cmp.size() > 0) {
- pw.println(" disabledComponents:");
- for (String s : cmp) {
- pw.print(" "); pw.println(s);
- }
- }
- cmp = ps.getEnabledComponents(user.id);
- if (cmp != null && cmp.size() > 0) {
- pw.println(" enabledComponents:");
- for (String s : cmp) {
- pw.print(" "); pw.println(s);
- }
- }
- }
- if (ps.grantedPermissions.size() > 0) {
- pw.println(" grantedPermissions:");
- for (String s : ps.grantedPermissions) {
- pw.print(" "); pw.println(s);
- }
- }
+ dumpPackageLPr(pw, " ", ps, sdf, date, users);
}
printedSomething = false;
@@ -2830,27 +2869,7 @@ final class Settings {
pw.println("Hidden system packages:");
printedSomething = true;
}
- pw.print(" Package [");
- pw.print(ps.realName != null ? ps.realName : ps.name);
- pw.print("] (");
- pw.print(Integer.toHexString(System.identityHashCode(ps)));
- pw.println("):");
- if (ps.realName != null) {
- pw.print(" compat name=");
- pw.println(ps.name);
- }
- if (ps.pkg != null && ps.pkg.applicationInfo != null) {
- pw.print(" applicationInfo=");
- pw.println(ps.pkg.applicationInfo.toString());
- }
- pw.print(" userId=");
- pw.println(ps.appId);
- pw.print(" sharedUser=");
- pw.println(ps.sharedUser);
- pw.print(" codePath=");
- pw.println(ps.codePathString);
- pw.print(" resourcePath=");
- pw.println(ps.resourcePathString);
+ dumpPackageLPr(pw, " ", ps, sdf, date, users);
}
}
}
diff --git a/services/java/com/android/server/power/ElectronBeam.java b/services/java/com/android/server/power/ElectronBeam.java
index 457e92d..4a74149 100644
--- a/services/java/com/android/server/power/ElectronBeam.java
+++ b/services/java/com/android/server/power/ElectronBeam.java
@@ -82,7 +82,7 @@ final class ElectronBeam {
private int mDisplayHeight; // real height, not rotated
private SurfaceSession mSurfaceSession;
private SurfaceControl mSurfaceControl;
- private final Surface mSurface = new Surface();
+ private Surface mSurface;
private NaturalSurfaceLayout mSurfaceLayout;
private EGLDisplay mEglDisplay;
private EGLConfig mEglConfig;
@@ -519,6 +519,7 @@ final class ElectronBeam {
mSurfaceControl.setLayerStack(mDisplayLayerStack);
mSurfaceControl.setSize(mDisplayWidth, mDisplayHeight);
+ mSurface = new Surface();
mSurface.copyFrom(mSurfaceControl);
mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManager, mSurfaceControl);
diff --git a/services/java/com/android/server/wifi/README.txt b/services/java/com/android/server/wifi/README.txt
new file mode 100644
index 0000000..c03bff5
--- /dev/null
+++ b/services/java/com/android/server/wifi/README.txt
@@ -0,0 +1,12 @@
+WifiService: Implements the IWifiManager 3rd party API. The API and the device state information (screen on/off, battery state, sleep policy) go as input into the WifiController which tracks high level states as to whether STA or AP mode is operational and controls the WifiStateMachine to handle bringup and shut down.
+
+WifiController: Acts as a controller to the WifiStateMachine based on various inputs (API and device state). Runs on the same thread created in WifiService.
+
+WifiSettingsStore: Tracks the various settings (wifi toggle, airplane toggle, tethering toggle, scan mode toggle) and provides API to figure if wifi should be turned on or off.
+
+WifiTrafficPoller: Polls traffic on wifi and notifies apps listening on it.
+
+WifiNotificationController: Controls whether the open network notification is displayed or not based on the scan results.
+
+WifiStateMachine: Tracks the various states on STA and AP connectivity and handles bring up and shut down.
+
diff --git a/services/java/com/android/server/wifi/WifiController.java b/services/java/com/android/server/wifi/WifiController.java
new file mode 100644
index 0000000..4d7c434
--- /dev/null
+++ b/services/java/com/android/server/wifi/WifiController.java
@@ -0,0 +1,626 @@
+/*
+ * 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.wifi;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import static android.net.wifi.WifiManager.WIFI_MODE_FULL;
+import static android.net.wifi.WifiManager.WIFI_MODE_FULL_HIGH_PERF;
+import static android.net.wifi.WifiManager.WIFI_MODE_SCAN_ONLY;
+import android.net.wifi.WifiStateMachine;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.WorkSource;
+import android.provider.Settings;
+import android.util.Slog;
+
+import com.android.internal.util.Protocol;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+import com.android.server.wifi.WifiService.LockList;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+class WifiController extends StateMachine {
+ private static final String TAG = "WifiController";
+ private static final boolean DBG = false;
+ private Context mContext;
+ private boolean mScreenOff;
+ private boolean mDeviceIdle;
+ private int mPluggedType;
+ private int mStayAwakeConditions;
+ private long mIdleMillis;
+ private int mSleepPolicy;
+
+ private AlarmManager mAlarmManager;
+ private PendingIntent mIdleIntent;
+ private static final int IDLE_REQUEST = 0;
+
+ /**
+ * See {@link Settings.Global#WIFI_IDLE_MS}. This is the default value if a
+ * Settings.Global value is not present. This timeout value is chosen as
+ * the approximate point at which the battery drain caused by Wi-Fi
+ * being enabled but not active exceeds the battery drain caused by
+ * re-establishing a connection to the mobile data network.
+ */
+ private static final long DEFAULT_IDLE_MS = 15 * 60 * 1000; /* 15 minutes */
+
+ NetworkInfo mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, "WIFI", "");
+
+ private static final String ACTION_DEVICE_IDLE =
+ "com.android.server.WifiManager.action.DEVICE_IDLE";
+
+ /* References to values tracked in WifiService */
+ final WifiStateMachine mWifiStateMachine;
+ final WifiSettingsStore mSettingsStore;
+ final LockList mLocks;
+
+ /**
+ * Temporary for computing UIDS that are responsible for starting WIFI.
+ * Protected by mWifiStateTracker lock.
+ */
+ private final WorkSource mTmpWorkSource = new WorkSource();
+
+ private static final int BASE = Protocol.BASE_WIFI_CONTROLLER;
+
+ static final int CMD_EMERGENCY_MODE_CHANGED = BASE + 1;
+ static final int CMD_SCREEN_ON = BASE + 2;
+ static final int CMD_SCREEN_OFF = BASE + 3;
+ static final int CMD_BATTERY_CHANGED = BASE + 4;
+ static final int CMD_DEVICE_IDLE = BASE + 5;
+ static final int CMD_LOCKS_CHANGED = BASE + 6;
+ static final int CMD_SCAN_ALWAYS_MODE_CHANGED = BASE + 7;
+ static final int CMD_WIFI_TOGGLED = BASE + 8;
+ static final int CMD_AIRPLANE_TOGGLED = BASE + 9;
+ static final int CMD_SET_AP = BASE + 10;
+
+ private DefaultState mDefaultState = new DefaultState();
+ private StaEnabledState mStaEnabledState = new StaEnabledState();
+ private ApStaDisabledState mApStaDisabledState = new ApStaDisabledState();
+ private StaDisabledWithScanState mStaDisabledWithScanState = new StaDisabledWithScanState();
+ private ApEnabledState mApEnabledState = new ApEnabledState();
+ private DeviceActiveState mDeviceActiveState = new DeviceActiveState();
+ private DeviceInactiveState mDeviceInactiveState = new DeviceInactiveState();
+ private ScanOnlyLockHeldState mScanOnlyLockHeldState = new ScanOnlyLockHeldState();
+ private FullLockHeldState mFullLockHeldState = new FullLockHeldState();
+ private FullHighPerfLockHeldState mFullHighPerfLockHeldState = new FullHighPerfLockHeldState();
+ private NoLockHeldState mNoLockHeldState = new NoLockHeldState();
+ private EcmState mEcmState = new EcmState();
+
+ WifiController(Context context, WifiService service, Looper looper) {
+ super(TAG, looper);
+ mContext = context;
+ mWifiStateMachine = service.mWifiStateMachine;
+ mSettingsStore = service.mSettingsStore;
+ mLocks = service.mLocks;
+
+ mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
+ Intent idleIntent = new Intent(ACTION_DEVICE_IDLE, null);
+ mIdleIntent = PendingIntent.getBroadcast(mContext, IDLE_REQUEST, idleIntent, 0);
+
+ addState(mDefaultState);
+ addState(mApStaDisabledState, mDefaultState);
+ addState(mStaEnabledState, mDefaultState);
+ addState(mDeviceActiveState, mStaEnabledState);
+ addState(mDeviceInactiveState, mStaEnabledState);
+ addState(mScanOnlyLockHeldState, mDeviceInactiveState);
+ addState(mFullLockHeldState, mDeviceInactiveState);
+ addState(mFullHighPerfLockHeldState, mDeviceInactiveState);
+ addState(mNoLockHeldState, mDeviceInactiveState);
+ addState(mStaDisabledWithScanState, mDefaultState);
+ addState(mApEnabledState, mDefaultState);
+ addState(mEcmState, mDefaultState);
+ setInitialState(mApStaDisabledState);
+ setLogRecSize(25);
+ setLogOnlyTransitions(true);
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(ACTION_DEVICE_IDLE);
+ filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ mContext.registerReceiver(
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(ACTION_DEVICE_IDLE)) {
+ sendMessage(CMD_DEVICE_IDLE);
+ } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+ mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
+ WifiManager.EXTRA_NETWORK_INFO);
+ }
+ }
+ },
+ new IntentFilter(filter));
+
+ initializeAndRegisterForSettingsChange(looper);
+ }
+
+ private void initializeAndRegisterForSettingsChange(Looper looper) {
+ Handler handler = new Handler(looper);
+ readStayAwakeConditions();
+ registerForStayAwakeModeChange(handler);
+ readWifiIdleTime();
+ registerForWifiIdleTimeChange(handler);
+ readStayAwakeConditions();
+ registerForWifiSleepPolicyChange(handler);
+ }
+
+ private void readStayAwakeConditions() {
+ mStayAwakeConditions = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0);
+ }
+
+ private void readWifiIdleTime() {
+ mIdleMillis = Settings.Global.getLong(mContext.getContentResolver(),
+ Settings.Global.WIFI_IDLE_MS, DEFAULT_IDLE_MS);
+ }
+
+ private void readWifiSleepPolicy() {
+ mSleepPolicy = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_SLEEP_POLICY,
+ Settings.Global.WIFI_SLEEP_POLICY_NEVER);
+ }
+
+ /**
+ * Observes settings changes to scan always mode.
+ */
+ private void registerForStayAwakeModeChange(Handler handler) {
+ ContentObserver contentObserver = new ContentObserver(handler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ readStayAwakeConditions();
+ }
+ };
+
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.STAY_ON_WHILE_PLUGGED_IN),
+ false, contentObserver);
+ }
+
+ /**
+ * Observes settings changes to scan always mode.
+ */
+ private void registerForWifiIdleTimeChange(Handler handler) {
+ ContentObserver contentObserver = new ContentObserver(handler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ readWifiIdleTime();
+ }
+ };
+
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.WIFI_IDLE_MS),
+ false, contentObserver);
+ }
+
+ /**
+ * Observes changes to wifi sleep policy
+ */
+ private void registerForWifiSleepPolicyChange(Handler handler) {
+ ContentObserver contentObserver = new ContentObserver(handler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ readWifiSleepPolicy();
+ }
+ };
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.WIFI_SLEEP_POLICY),
+ false, contentObserver);
+ }
+
+ /**
+ * Determines whether the Wi-Fi chipset should stay awake or be put to
+ * sleep. Looks at the setting for the sleep policy and the current
+ * conditions.
+ *
+ * @see #shouldDeviceStayAwake(int)
+ */
+ private boolean shouldWifiStayAwake(int pluggedType) {
+ if (mSleepPolicy == Settings.Global.WIFI_SLEEP_POLICY_NEVER) {
+ // Never sleep
+ return true;
+ } else if ((mSleepPolicy == Settings.Global.WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED) &&
+ (pluggedType != 0)) {
+ // Never sleep while plugged, and we're plugged
+ return true;
+ } else {
+ // Default
+ return shouldDeviceStayAwake(pluggedType);
+ }
+ }
+
+ /**
+ * Determine whether the bit value corresponding to {@code pluggedType} is set in
+ * the bit string mStayAwakeConditions. This determines whether the device should
+ * stay awake based on the current plugged type.
+ *
+ * @param pluggedType the type of plug (USB, AC, or none) for which the check is
+ * being made
+ * @return {@code true} if {@code pluggedType} indicates that the device is
+ * supposed to stay awake, {@code false} otherwise.
+ */
+ private boolean shouldDeviceStayAwake(int pluggedType) {
+ return (mStayAwakeConditions & pluggedType) != 0;
+ }
+
+ private void updateBatteryWorkSource() {
+ mTmpWorkSource.clear();
+ if (mDeviceIdle) {
+ mLocks.updateWorkSource(mTmpWorkSource);
+ }
+ mWifiStateMachine.updateBatteryWorkSource(mTmpWorkSource);
+ }
+
+ class DefaultState extends State {
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_SCREEN_ON:
+ mAlarmManager.cancel(mIdleIntent);
+ mScreenOff = false;
+ mDeviceIdle = false;
+ updateBatteryWorkSource();
+ break;
+ case CMD_SCREEN_OFF:
+ mScreenOff = true;
+ /*
+ * Set a timer to put Wi-Fi to sleep, but only if the screen is off
+ * AND the "stay on while plugged in" setting doesn't match the
+ * current power conditions (i.e, not plugged in, plugged in to USB,
+ * or plugged in to AC).
+ */
+ if (!shouldWifiStayAwake(mPluggedType)) {
+ //Delayed shutdown if wifi is connected
+ if (mNetworkInfo.getDetailedState() ==
+ NetworkInfo.DetailedState.CONNECTED) {
+ if (DBG) Slog.d(TAG, "set idle timer: " + mIdleMillis + " ms");
+ mAlarmManager.set(AlarmManager.RTC_WAKEUP,
+ System.currentTimeMillis() + mIdleMillis, mIdleIntent);
+ } else {
+ sendMessage(CMD_DEVICE_IDLE);
+ }
+ }
+ break;
+ case CMD_DEVICE_IDLE:
+ mDeviceIdle = true;
+ updateBatteryWorkSource();
+ break;
+ case CMD_BATTERY_CHANGED:
+ /*
+ * Set a timer to put Wi-Fi to sleep, but only if the screen is off
+ * AND we are transitioning from a state in which the device was supposed
+ * to stay awake to a state in which it is not supposed to stay awake.
+ * If "stay awake" state is not changing, we do nothing, to avoid resetting
+ * the already-set timer.
+ */
+ int pluggedType = msg.arg1;
+ if (DBG) Slog.d(TAG, "battery changed pluggedType: " + pluggedType);
+ if (mScreenOff && shouldWifiStayAwake(mPluggedType) &&
+ !shouldWifiStayAwake(pluggedType)) {
+ long triggerTime = System.currentTimeMillis() + mIdleMillis;
+ if (DBG) Slog.d(TAG, "set idle timer for " + mIdleMillis + "ms");
+ mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
+ }
+
+ mPluggedType = pluggedType;
+ break;
+ case CMD_SET_AP:
+ case CMD_SCAN_ALWAYS_MODE_CHANGED:
+ case CMD_LOCKS_CHANGED:
+ case CMD_WIFI_TOGGLED:
+ case CMD_AIRPLANE_TOGGLED:
+ case CMD_EMERGENCY_MODE_CHANGED:
+ break;
+ default:
+ throw new RuntimeException("WifiController.handleMessage " + msg.what);
+ }
+ return HANDLED;
+ }
+
+ }
+
+ class ApStaDisabledState extends State {
+ @Override
+ public void enter() {
+ mWifiStateMachine.setSupplicantRunning(false);
+ }
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_WIFI_TOGGLED:
+ case CMD_AIRPLANE_TOGGLED:
+ if (mSettingsStore.isWifiToggleEnabled()) {
+ if (mDeviceIdle == false) {
+ transitionTo(mDeviceActiveState);
+ } else {
+ checkLocksAndTransitionWhenDeviceIdle();
+ }
+ }
+ break;
+ case CMD_SCAN_ALWAYS_MODE_CHANGED:
+ if (mSettingsStore.isScanAlwaysAvailable()) {
+ transitionTo(mStaDisabledWithScanState);
+ }
+ break;
+ case CMD_SET_AP:
+ if (msg.arg1 == 1) {
+ mWifiStateMachine.setHostApRunning((WifiConfiguration) msg.obj,
+ true);
+ transitionTo(mApEnabledState);
+ }
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return HANDLED;
+ }
+
+ }
+
+ class StaEnabledState extends State {
+ @Override
+ public void enter() {
+ mWifiStateMachine.setSupplicantRunning(true);
+ }
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_WIFI_TOGGLED:
+ if (! mSettingsStore.isWifiToggleEnabled()) {
+ if (mSettingsStore.isScanAlwaysAvailable()) {
+ transitionTo(mStaDisabledWithScanState);
+ } else {
+ transitionTo(mApStaDisabledState);
+ }
+ }
+ break;
+ case CMD_AIRPLANE_TOGGLED:
+ /* When wi-fi is turned off due to airplane,
+ * disable entirely (including scan)
+ */
+ if (! mSettingsStore.isWifiToggleEnabled()) {
+ transitionTo(mApStaDisabledState);
+ }
+ break;
+ case CMD_EMERGENCY_MODE_CHANGED:
+ if (msg.arg1 == 1) {
+ transitionTo(mEcmState);
+ break;
+ }
+ default:
+ return NOT_HANDLED;
+
+ }
+ return HANDLED;
+ }
+ }
+
+ class StaDisabledWithScanState extends State {
+ @Override
+ public void enter() {
+ mWifiStateMachine.setSupplicantRunning(true);
+ mWifiStateMachine.setOperationalMode(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE);
+ mWifiStateMachine.setDriverStart(true);
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_WIFI_TOGGLED:
+ if (mSettingsStore.isWifiToggleEnabled()) {
+ if (mDeviceIdle == false) {
+ transitionTo(mDeviceActiveState);
+ } else {
+ checkLocksAndTransitionWhenDeviceIdle();
+ }
+ }
+ break;
+ case CMD_AIRPLANE_TOGGLED:
+ if (mSettingsStore.isAirplaneModeOn() &&
+ ! mSettingsStore.isWifiToggleEnabled()) {
+ transitionTo(mApStaDisabledState);
+ }
+ case CMD_SCAN_ALWAYS_MODE_CHANGED:
+ if (! mSettingsStore.isScanAlwaysAvailable()) {
+ transitionTo(mApStaDisabledState);
+ }
+ break;
+ case CMD_SET_AP:
+ // Before starting tethering, turn off supplicant for scan mode
+ if (msg.arg1 == 1) {
+ deferMessage(msg);
+ transitionTo(mApStaDisabledState);
+ }
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return HANDLED;
+ }
+ }
+
+ class ApEnabledState extends State {
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_AIRPLANE_TOGGLED:
+ if (mSettingsStore.isAirplaneModeOn()) {
+ mWifiStateMachine.setHostApRunning(null, false);
+ transitionTo(mApStaDisabledState);
+ }
+ break;
+ case CMD_SET_AP:
+ if (msg.arg1 == 0) {
+ mWifiStateMachine.setHostApRunning(null, false);
+ transitionTo(mApStaDisabledState);
+ }
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return HANDLED;
+ }
+ }
+
+ class EcmState extends State {
+ @Override
+ public void enter() {
+ mWifiStateMachine.setSupplicantRunning(false);
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ if (msg.what == CMD_EMERGENCY_MODE_CHANGED && msg.arg1 == 0) {
+ if (mSettingsStore.isWifiToggleEnabled()) {
+ if (mDeviceIdle == false) {
+ transitionTo(mDeviceActiveState);
+ } else {
+ checkLocksAndTransitionWhenDeviceIdle();
+ }
+ } else if (mSettingsStore.isScanAlwaysAvailable()) {
+ transitionTo(mStaDisabledWithScanState);
+ } else {
+ transitionTo(mApStaDisabledState);
+ }
+ return HANDLED;
+ } else {
+ return NOT_HANDLED;
+ }
+ }
+ }
+
+ /* Parent: StaEnabledState */
+ class DeviceActiveState extends State {
+ @Override
+ public void enter() {
+ mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE);
+ mWifiStateMachine.setDriverStart(true);
+ mWifiStateMachine.setHighPerfModeEnabled(false);
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ if (msg.what == CMD_DEVICE_IDLE) {
+ checkLocksAndTransitionWhenDeviceIdle();
+ // We let default state handle the rest of work
+ }
+ return NOT_HANDLED;
+ }
+ }
+
+ /* Parent: StaEnabledState */
+ class DeviceInactiveState extends State {
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_LOCKS_CHANGED:
+ checkLocksAndTransitionWhenDeviceIdle();
+ updateBatteryWorkSource();
+ return HANDLED;
+ case CMD_SCREEN_ON:
+ transitionTo(mDeviceActiveState);
+ // More work in default state
+ return NOT_HANDLED;
+ default:
+ return NOT_HANDLED;
+ }
+ }
+ }
+
+ /* Parent: DeviceInactiveState. Device is inactive, but an app is holding a scan only lock. */
+ class ScanOnlyLockHeldState extends State {
+ @Override
+ public void enter() {
+ mWifiStateMachine.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE);
+ mWifiStateMachine.setDriverStart(true);
+ }
+ }
+
+ /* Parent: DeviceInactiveState. Device is inactive, but an app is holding a full lock. */
+ class FullLockHeldState extends State {
+ @Override
+ public void enter() {
+ mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE);
+ mWifiStateMachine.setDriverStart(true);
+ mWifiStateMachine.setHighPerfModeEnabled(false);
+ }
+ }
+
+ /* Parent: DeviceInactiveState. Device is inactive, but an app is holding a high perf lock. */
+ class FullHighPerfLockHeldState extends State {
+ @Override
+ public void enter() {
+ mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE);
+ mWifiStateMachine.setDriverStart(true);
+ mWifiStateMachine.setHighPerfModeEnabled(true);
+ }
+ }
+
+ /* Parent: DeviceInactiveState. Device is inactive and no app is holding a wifi lock. */
+ class NoLockHeldState extends State {
+ @Override
+ public void enter() {
+ mWifiStateMachine.setDriverStart(false);
+ }
+ }
+
+ private void checkLocksAndTransitionWhenDeviceIdle() {
+ if (mLocks.hasLocks()) {
+ switch (mLocks.getStrongestLockMode()) {
+ case WIFI_MODE_FULL:
+ transitionTo(mFullLockHeldState);
+ break;
+ case WIFI_MODE_FULL_HIGH_PERF:
+ transitionTo(mFullHighPerfLockHeldState);
+ break;
+ case WIFI_MODE_SCAN_ONLY:
+ transitionTo(mScanOnlyLockHeldState);
+ break;
+ default:
+ loge("Illegal lock " + mLocks.getStrongestLockMode());
+ }
+ } else {
+ if (mSettingsStore.isScanAlwaysAvailable()) {
+ transitionTo(mScanOnlyLockHeldState);
+ } else {
+ transitionTo(mNoLockHeldState);
+ }
+ }
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ super.dump(fd, pw, args);
+
+ pw.println("mScreenOff " + mScreenOff);
+ pw.println("mDeviceIdle " + mDeviceIdle);
+ pw.println("mPluggedType " + mPluggedType);
+ pw.println("mIdleMillis " + mIdleMillis);
+ pw.println("mSleepPolicy " + mSleepPolicy);
+ }
+}
diff --git a/services/java/com/android/server/wifi/WifiService.java b/services/java/com/android/server/wifi/WifiService.java
index d675822..bc6bdaf 100644
--- a/services/java/com/android/server/wifi/WifiService.java
+++ b/services/java/com/android/server/wifi/WifiService.java
@@ -17,15 +17,14 @@
package com.android.server.wifi;
import android.app.ActivityManager;
-import android.app.AlarmManager;
import android.app.AppOpsManager;
-import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.database.ContentObserver;
import android.net.wifi.IWifiManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiInfo;
@@ -33,12 +32,9 @@ import android.net.wifi.WifiManager;
import android.net.wifi.WifiStateMachine;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiWatchdogStateMachine;
-import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.DhcpResults;
import android.net.LinkAddress;
-import android.net.NetworkInfo;
-import android.net.NetworkInfo.DetailedState;
import android.net.NetworkUtils;
import android.net.RouteInfo;
import android.os.Binder;
@@ -63,39 +59,35 @@ import java.net.Inet4Address;
import java.util.ArrayList;
import java.util.List;
+import com.android.internal.R;
import com.android.internal.app.IBatteryStats;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.AsyncChannel;
import com.android.server.am.BatteryStatsService;
-import com.android.internal.R;
-
+import static com.android.server.wifi.WifiController.CMD_AIRPLANE_TOGGLED;
+import static com.android.server.wifi.WifiController.CMD_BATTERY_CHANGED;
+import static com.android.server.wifi.WifiController.CMD_EMERGENCY_MODE_CHANGED;
+import static com.android.server.wifi.WifiController.CMD_LOCKS_CHANGED;
+import static com.android.server.wifi.WifiController.CMD_SCAN_ALWAYS_MODE_CHANGED;
+import static com.android.server.wifi.WifiController.CMD_SCREEN_OFF;
+import static com.android.server.wifi.WifiController.CMD_SCREEN_ON;
+import static com.android.server.wifi.WifiController.CMD_SET_AP;
+import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED;
/**
* WifiService handles remote WiFi operation requests by implementing
* the IWifiManager interface.
*
* @hide
*/
-//TODO: Clean up multiple locks and implement WifiService
-// as a SM to track soft AP/client/adhoc bring up based
-// on device idle state, airplane mode and boot.
-
public final class WifiService extends IWifiManager.Stub {
private static final String TAG = "WifiService";
private static final boolean DBG = false;
- private final WifiStateMachine mWifiStateMachine;
+ final WifiStateMachine mWifiStateMachine;
private final Context mContext;
- private AlarmManager mAlarmManager;
- private PendingIntent mIdleIntent;
- private static final int IDLE_REQUEST = 0;
- private boolean mScreenOff;
- private boolean mDeviceIdle;
- private boolean mEmergencyCallbackMode = false;
- private int mPluggedType;
-
- private final LockList mLocks = new LockList();
+ final LockList mLocks = new LockList();
// some wifi lock statistics
private int mFullHighPerfLocksAcquired;
private int mFullHighPerfLocksReleased;
@@ -119,19 +111,7 @@ public final class WifiService extends IWifiManager.Stub {
/* Polls traffic stats and notifies clients */
private WifiTrafficPoller mTrafficPoller;
/* Tracks the persisted states for wi-fi & airplane mode */
- private WifiSettingsStore mSettingsStore;
-
- /**
- * See {@link Settings.Global#WIFI_IDLE_MS}. This is the default value if a
- * Settings.Global value is not present. This timeout value is chosen as
- * the approximate point at which the battery drain caused by Wi-Fi
- * being enabled but not active exceeds the battery drain caused by
- * re-establishing a connection to the mobile data network.
- */
- private static final long DEFAULT_IDLE_MS = 15 * 60 * 1000; /* 15 minutes */
-
- private static final String ACTION_DEVICE_IDLE =
- "com.android.server.WifiManager.action.DEVICE_IDLE";
+ final WifiSettingsStore mSettingsStore;
/* The work source (UID) that triggered the current WIFI scan, synchronized
* on this */
@@ -139,8 +119,6 @@ public final class WifiService extends IWifiManager.Stub {
private boolean mIsReceiverRegistered = false;
- NetworkInfo mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, "WIFI", "");
-
/**
* Asynchronous channel to WifiStateMachine
*/
@@ -195,7 +173,7 @@ public final class WifiService extends IWifiManager.Stub {
break;
}
default: {
- Slog.d(TAG, "WifiServicehandler.handleMessage ignoring msg=" + msg);
+ Slog.d(TAG, "ClientHandler.handleMessage ignoring msg=" + msg);
break;
}
}
@@ -243,11 +221,6 @@ public final class WifiService extends IWifiManager.Stub {
}
WifiStateMachineHandler mWifiStateMachineHandler;
- /**
- * Temporary for computing UIDS that are responsible for starting WIFI.
- * Protected by mWifiStateTracker lock.
- */
- private final WorkSource mTmpWorkSource = new WorkSource();
private WifiWatchdogStateMachine mWifiWatchdogStateMachine;
public WifiService(Context context) {
@@ -260,20 +233,24 @@ public final class WifiService extends IWifiManager.Stub {
mBatteryStats = BatteryStatsService.getService();
mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
- mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
- Intent idleIntent = new Intent(ACTION_DEVICE_IDLE, null);
- mIdleIntent = PendingIntent.getBroadcast(mContext, IDLE_REQUEST, idleIntent, 0);
-
mNotificationController = new WifiNotificationController(mContext, mWifiStateMachine);
mTrafficPoller = new WifiTrafficPoller(mContext, mInterfaceName);
mSettingsStore = new WifiSettingsStore(mContext);
+ HandlerThread wifiThread = new HandlerThread("WifiService");
+ wifiThread.start();
+ mClientHandler = new ClientHandler(wifiThread.getLooper());
+ mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper());
+ mWifiController = new WifiController(mContext, this, wifiThread.getLooper());
+ mWifiController.start();
+
+ registerForScanModeChange();
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (mSettingsStore.handleAirplaneModeToggled()) {
- updateWifiState();
+ mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED);
}
}
},
@@ -289,13 +266,10 @@ public final class WifiService extends IWifiManager.Stub {
}
}
}, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
-
- HandlerThread wifiThread = new HandlerThread("WifiService");
- wifiThread.start();
- mClientHandler = new ClientHandler(wifiThread.getLooper());
- mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper());
}
+ private WifiController mWifiController;
+
/** Tell battery stats about a new WIFI scan */
private void noteScanStart() {
WorkSource scanWorkSource = null;
@@ -342,7 +316,7 @@ public final class WifiService extends IWifiManager.Stub {
*/
public void checkAndStartWifi() {
/* Check if wi-fi needs to be enabled */
- boolean wifiEnabled = mSettingsStore.shouldWifiBeEnabled();
+ boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();
Slog.i(TAG, "WifiService starting up with Wi-Fi " +
(wifiEnabled ? "enabled" : "disabled"));
@@ -430,11 +404,7 @@ public final class WifiService extends IWifiManager.Stub {
Binder.restoreCallingIdentity(ident);
}
- if (enable) {
- reportStartWorkSource();
- }
-
- mWifiStateMachine.setWifiEnabled(enable);
+ mWifiController.sendMessage(CMD_WIFI_TOGGLED);
if (enable) {
if (!mIsReceiverRegistered) {
@@ -470,7 +440,7 @@ public final class WifiService extends IWifiManager.Stub {
*/
public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
enforceChangePermission();
- mWifiStateMachine.setWifiApEnabled(wifiConfig, enabled);
+ mWifiController.obtainMessage(CMD_SET_AP, enabled ? 1 : 0, 0, wifiConfig).sendToTarget();
}
/**
@@ -507,6 +477,26 @@ public final class WifiService extends IWifiManager.Stub {
}
/**
+ * @param enable {@code true} to enable, {@code false} to disable.
+ * @return {@code true} if the enable/disable operation was
+ * started or is already in the queue.
+ */
+ public boolean isScanningAlwaysAvailable() {
+ // TODO: implement
+ return true;
+ }
+
+ /**
+ * @param enable {@code true} to enable, {@code false} to disable.
+ * @return {@code true} if the enable/disable operation was
+ * started or is already in the queue.
+ */
+ public void setScanningAlwaysAvailable(boolean enable) {
+ // TODO: implement
+ }
+
+
+ /**
* see {@link android.net.wifi.WifiManager#disconnect()}
*/
public void disconnect() {
@@ -777,7 +767,7 @@ public final class WifiService extends IWifiManager.Stub {
* of WifiLock & device idle status unless wifi enabled status is toggled
*/
- mWifiStateMachine.setDriverStart(true, mEmergencyCallbackMode);
+ mWifiStateMachine.setDriverStart(true);
mWifiStateMachine.reconnectCommand();
}
@@ -796,7 +786,7 @@ public final class WifiService extends IWifiManager.Stub {
* TODO: if a stop is issued, wifi is brought up only by startWifi
* unless wifi enabled status is toggled
*/
- mWifiStateMachine.setDriverStart(false, mEmergencyCallbackMode);
+ mWifiStateMachine.setDriverStart(false);
}
/**
@@ -848,175 +838,39 @@ public final class WifiService extends IWifiManager.Stub {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
-
- long idleMillis =
- Settings.Global.getLong(mContext.getContentResolver(),
- Settings.Global.WIFI_IDLE_MS, DEFAULT_IDLE_MS);
- int stayAwakeConditions =
- Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0);
if (action.equals(Intent.ACTION_SCREEN_ON)) {
- if (DBG) {
- Slog.d(TAG, "ACTION_SCREEN_ON");
- }
- mAlarmManager.cancel(mIdleIntent);
- mScreenOff = false;
- setDeviceIdleAndUpdateWifi(false);
+ mWifiController.sendMessage(CMD_SCREEN_ON);
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
- if (DBG) {
- Slog.d(TAG, "ACTION_SCREEN_OFF");
- }
- mScreenOff = true;
- /*
- * Set a timer to put Wi-Fi to sleep, but only if the screen is off
- * AND the "stay on while plugged in" setting doesn't match the
- * current power conditions (i.e, not plugged in, plugged in to USB,
- * or plugged in to AC).
- */
- if (!shouldWifiStayAwake(stayAwakeConditions, mPluggedType)) {
- //Delayed shutdown if wifi is connected
- if (mNetworkInfo.getDetailedState() == DetailedState.CONNECTED) {
- if (DBG) Slog.d(TAG, "setting ACTION_DEVICE_IDLE: " + idleMillis + " ms");
- mAlarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
- + idleMillis, mIdleIntent);
- } else {
- setDeviceIdleAndUpdateWifi(true);
- }
- }
- } else if (action.equals(ACTION_DEVICE_IDLE)) {
- setDeviceIdleAndUpdateWifi(true);
+ mWifiController.sendMessage(CMD_SCREEN_OFF);
} else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
- /*
- * Set a timer to put Wi-Fi to sleep, but only if the screen is off
- * AND we are transitioning from a state in which the device was supposed
- * to stay awake to a state in which it is not supposed to stay awake.
- * If "stay awake" state is not changing, we do nothing, to avoid resetting
- * the already-set timer.
- */
int pluggedType = intent.getIntExtra("plugged", 0);
- if (DBG) {
- Slog.d(TAG, "ACTION_BATTERY_CHANGED pluggedType: " + pluggedType);
- }
- if (mScreenOff && shouldWifiStayAwake(stayAwakeConditions, mPluggedType) &&
- !shouldWifiStayAwake(stayAwakeConditions, pluggedType)) {
- long triggerTime = System.currentTimeMillis() + idleMillis;
- if (DBG) {
- Slog.d(TAG, "setting ACTION_DEVICE_IDLE timer for " + idleMillis + "ms");
- }
- mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
- }
-
- mPluggedType = pluggedType;
+ mWifiController.sendMessage(CMD_BATTERY_CHANGED, pluggedType, 0, null);
} else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
BluetoothAdapter.STATE_DISCONNECTED);
mWifiStateMachine.sendBluetoothAdapterStateChange(state);
} else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
- mEmergencyCallbackMode = intent.getBooleanExtra("phoneinECMState", false);
- updateWifiState();
+ boolean emergencyMode = intent.getBooleanExtra("phoneinECMState", false);
+ mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, emergencyMode ? 1 : 0, 0);
}
}
-
- /**
- * Determines whether the Wi-Fi chipset should stay awake or be put to
- * sleep. Looks at the setting for the sleep policy and the current
- * conditions.
- *
- * @see #shouldDeviceStayAwake(int, int)
- */
- private boolean shouldWifiStayAwake(int stayAwakeConditions, int pluggedType) {
- //Never sleep as long as the user has not changed the settings
- int wifiSleepPolicy = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.WIFI_SLEEP_POLICY,
- Settings.Global.WIFI_SLEEP_POLICY_NEVER);
-
- if (wifiSleepPolicy == Settings.Global.WIFI_SLEEP_POLICY_NEVER) {
- // Never sleep
- return true;
- } else if ((wifiSleepPolicy == Settings.Global.WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED) &&
- (pluggedType != 0)) {
- // Never sleep while plugged, and we're plugged
- return true;
- } else {
- // Default
- return shouldDeviceStayAwake(stayAwakeConditions, pluggedType);
- }
- }
-
- /**
- * Determine whether the bit value corresponding to {@code pluggedType} is set in
- * the bit string {@code stayAwakeConditions}. Because a {@code pluggedType} value
- * of {@code 0} isn't really a plugged type, but rather an indication that the
- * device isn't plugged in at all, there is no bit value corresponding to a
- * {@code pluggedType} value of {@code 0}. That is why we shift by
- * {@code pluggedType - 1} instead of by {@code pluggedType}.
- * @param stayAwakeConditions a bit string specifying which "plugged types" should
- * keep the device (and hence Wi-Fi) awake.
- * @param pluggedType the type of plug (USB, AC, or none) for which the check is
- * being made
- * @return {@code true} if {@code pluggedType} indicates that the device is
- * supposed to stay awake, {@code false} otherwise.
- */
- private boolean shouldDeviceStayAwake(int stayAwakeConditions, int pluggedType) {
- return (stayAwakeConditions & pluggedType) != 0;
- }
};
- private void setDeviceIdleAndUpdateWifi(boolean deviceIdle) {
- mDeviceIdle = deviceIdle;
- reportStartWorkSource();
- updateWifiState();
- }
-
- private synchronized void reportStartWorkSource() {
- mTmpWorkSource.clear();
- if (mDeviceIdle) {
- for (int i=0; i<mLocks.mList.size(); i++) {
- mTmpWorkSource.add(mLocks.mList.get(i).mWorkSource);
+ /**
+ * Observes settings changes to scan always mode.
+ */
+ private void registerForScanModeChange() {
+ ContentObserver contentObserver = new ContentObserver(null) {
+ @Override
+ public void onChange(boolean selfChange) {
+ mSettingsStore.handleWifiScanAlwaysAvailableToggled();
+ mWifiController.sendMessage(CMD_SCAN_ALWAYS_MODE_CHANGED);
}
- }
- mWifiStateMachine.updateBatteryWorkSource(mTmpWorkSource);
- }
-
- private void updateWifiState() {
- boolean lockHeld = mLocks.hasLocks();
- int strongestLockMode = WifiManager.WIFI_MODE_FULL;
- boolean wifiShouldBeStarted;
-
- if (mEmergencyCallbackMode) {
- wifiShouldBeStarted = false;
- } else {
- wifiShouldBeStarted = !mDeviceIdle || lockHeld;
- }
-
- if (lockHeld) {
- strongestLockMode = mLocks.getStrongestLockMode();
- }
- /* If device is not idle, lockmode cannot be scan only */
- if (!mDeviceIdle && strongestLockMode == WifiManager.WIFI_MODE_SCAN_ONLY) {
- strongestLockMode = WifiManager.WIFI_MODE_FULL;
- }
-
- /* Disable tethering when airplane mode is enabled */
- if (mSettingsStore.isAirplaneModeOn()) {
- mWifiStateMachine.setWifiApEnabled(null, false);
- }
+ };
- if (mSettingsStore.shouldWifiBeEnabled()) {
- if (wifiShouldBeStarted) {
- reportStartWorkSource();
- mWifiStateMachine.setWifiEnabled(true);
- mWifiStateMachine.setScanOnlyMode(
- strongestLockMode == WifiManager.WIFI_MODE_SCAN_ONLY);
- mWifiStateMachine.setDriverStart(true, mEmergencyCallbackMode);
- mWifiStateMachine.setHighPerfModeEnabled(strongestLockMode
- == WifiManager.WIFI_MODE_FULL_HIGH_PERF);
- } else {
- mWifiStateMachine.setDriverStart(false, mEmergencyCallbackMode);
- }
- } else {
- mWifiStateMachine.setWifiEnabled(false);
- }
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE),
+ false, contentObserver);
}
private void registerForBroadcasts() {
@@ -1024,7 +878,7 @@ public final class WifiService extends IWifiManager.Stub {
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
- intentFilter.addAction(ACTION_DEVICE_IDLE);
+ intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
mContext.registerReceiver(mReceiver, intentFilter);
@@ -1043,12 +897,9 @@ public final class WifiService extends IWifiManager.Stub {
pw.println("Stay-awake conditions: " +
Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0));
- pw.println("mScreenOff " + mScreenOff);
- pw.println("mDeviceIdle " + mDeviceIdle);
- pw.println("mPluggedType " + mPluggedType);
- pw.println("mEmergencyCallbackMode " + mEmergencyCallbackMode);
pw.println("mMulticastEnabled " + mMulticastEnabled);
pw.println("mMulticastDisabled " + mMulticastDisabled);
+ mWifiController.dump(fd, pw, args);
mSettingsStore.dump(fd, pw, args);
mNotificationController.dump(fd, pw, args);
mTrafficPoller.dump(fd, pw, args);
@@ -1099,18 +950,18 @@ public final class WifiService extends IWifiManager.Stub {
}
}
- private class LockList {
+ class LockList {
private List<WifiLock> mList;
private LockList() {
mList = new ArrayList<WifiLock>();
}
- private synchronized boolean hasLocks() {
+ synchronized boolean hasLocks() {
return !mList.isEmpty();
}
- private synchronized int getStrongestLockMode() {
+ synchronized int getStrongestLockMode() {
if (mList.isEmpty()) {
return WifiManager.WIFI_MODE_FULL;
}
@@ -1126,6 +977,12 @@ public final class WifiService extends IWifiManager.Stub {
return WifiManager.WIFI_MODE_SCAN_ONLY;
}
+ synchronized void updateWorkSource(WorkSource ws) {
+ for (int i = 0; i < mLocks.mList.size(); i++) {
+ ws.add(mLocks.mList.get(i).mWorkSource);
+ }
+ }
+
private void addLock(WifiLock lock) {
if (findLockByBinder(lock.mBinder) < 0) {
mList.add(lock);
@@ -1145,9 +1002,10 @@ public final class WifiService extends IWifiManager.Stub {
private int findLockByBinder(IBinder binder) {
int size = mList.size();
- for (int i = size - 1; i >= 0; i--)
+ for (int i = size - 1; i >= 0; i--) {
if (mList.get(i).mBinder == binder)
return i;
+ }
return -1;
}
@@ -1231,12 +1089,7 @@ public final class WifiService extends IWifiManager.Stub {
++mScanLocksAcquired;
break;
}
-
- // Be aggressive about adding new locks into the accounted state...
- // we want to over-report rather than under-report.
- reportStartWorkSource();
-
- updateWifiState();
+ mWifiController.sendMessage(CMD_LOCKS_CHANGED);
return true;
} catch (RemoteException e) {
return false;
@@ -1303,11 +1156,8 @@ public final class WifiService extends IWifiManager.Stub {
++mScanLocksReleased;
break;
}
+ mWifiController.sendMessage(CMD_LOCKS_CHANGED);
}
-
- // TODO - should this only happen if you hadLock?
- updateWifiState();
-
} catch (RemoteException e) {
} finally {
Binder.restoreCallingIdentity(ident);
diff --git a/services/java/com/android/server/wifi/WifiSettingsStore.java b/services/java/com/android/server/wifi/WifiSettingsStore.java
index d7c8752..3ff8061 100644
--- a/services/java/com/android/server/wifi/WifiSettingsStore.java
+++ b/services/java/com/android/server/wifi/WifiSettingsStore.java
@@ -37,7 +37,11 @@ final class WifiSettingsStore {
private int mPersistWifiState = WIFI_DISABLED;
/* Tracks current airplane mode state */
private boolean mAirplaneModeOn = false;
- /* Tracks whether wifi is enabled from WifiStateMachine's perspective */
+
+ /* Tracks the setting of scan being available even when wi-fi is turned off
+ */
+ private boolean mScanAlwaysAvailable;
+
private final Context mContext;
/* Tracks if we have checked the saved wi-fi state after boot */
@@ -47,9 +51,10 @@ final class WifiSettingsStore {
mContext = context;
mAirplaneModeOn = getPersistedAirplaneModeOn();
mPersistWifiState = getPersistedWifiState();
+ mScanAlwaysAvailable = getPersistedScanAlwaysAvailable();
}
- synchronized boolean shouldWifiBeEnabled() {
+ synchronized boolean isWifiToggleEnabled() {
if (!mCheckSavedStateAtBoot) {
mCheckSavedStateAtBoot = true;
if (testAndClearWifiSavedState()) return true;
@@ -70,6 +75,10 @@ final class WifiSettingsStore {
return mAirplaneModeOn;
}
+ synchronized boolean isScanAlwaysAvailable() {
+ return mScanAlwaysAvailable;
+ }
+
synchronized boolean handleWifiToggled(boolean wifiEnabled) {
// Can Wi-Fi be toggled in airplane mode ?
if (mAirplaneModeOn && !isAirplaneToggleable()) {
@@ -114,6 +123,10 @@ final class WifiSettingsStore {
return true;
}
+ synchronized void handleWifiScanAlwaysAvailableToggled() {
+ mScanAlwaysAvailable = getPersistedScanAlwaysAvailable();
+ }
+
void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("mPersistWifiState " + mPersistWifiState);
pw.println("mAirplaneModeOn " + mAirplaneModeOn);
@@ -175,4 +188,10 @@ final class WifiSettingsStore {
return Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
}
+
+ private boolean getPersistedScanAlwaysAvailable() {
+ return Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE,
+ 0) == 1;
+ }
}