diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index cfc2e755e3869..659d70fd56e34 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -92,11 +92,6 @@ public final class Pm { return; } - if ("mountsd".equals(op)) { - runMountSd(); - return; - } - if ("uninstall".equals(op)) { runUninstall(); return; @@ -646,37 +641,6 @@ public final class Pm { } } - private void runMountSd() { - String opt; - boolean mount = false; - while ((opt=nextOption()) != null) { - if (opt.equals("-m")) { - String mountStr = nextOptionData(); - if (mountStr == null) { - System.err.println("Error: no value specified for -m"); - showUsage(); - return; - } - if ("true".equalsIgnoreCase(mountStr)) { - mount = true; - } else if ("false".equalsIgnoreCase(mountStr)) { - mount = false; - } else { - System.err.println("Error: no value specified for -m"); - showUsage(); - return; - } - } - } - - try { - mPm.updateExternalMediaStatus(mount); - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(PM_NOT_RUNNING_ERR); - } - } - class PackageDeleteObserver extends IPackageDeleteObserver.Stub { boolean finished; boolean result; @@ -866,7 +830,6 @@ public final class Pm { System.err.println(" pm path PACKAGE"); System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH"); System.err.println(" pm uninstall [-k] PACKAGE"); - System.err.println(" pm mountsd [-m true/false]"); System.err.println(" pm enable PACKAGE_OR_COMPONENT"); System.err.println(" pm disable PACKAGE_OR_COMPONENT"); System.err.println(""); diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 6d5686a40c336..596ca9de7ba4e 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -980,10 +980,11 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } - case KILL_PIDS_FOR_MEMORY_TRANSACTION: { + case KILL_PIDS_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); int[] pids = data.createIntArray(); - boolean res = killPidsForMemory(pids); + String reason = data.readString(); + boolean res = killPids(pids, reason); reply.writeNoException(); reply.writeInt(res ? 1 : 0); return true; @@ -2393,12 +2394,13 @@ class ActivityManagerProxy implements IActivityManager mRemote.transact(NOTE_WAKEUP_ALARM_TRANSACTION, data, null, 0); data.recycle(); } - public boolean killPidsForMemory(int[] pids) throws RemoteException { + public boolean killPids(int[] pids, String reason) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeIntArray(pids); - mRemote.transact(KILL_PIDS_FOR_MEMORY_TRANSACTION, data, reply, 0); + data.writeString(reason); + mRemote.transact(KILL_PIDS_TRANSACTION, data, reply, 0); boolean res = reply.readInt() != 0; data.recycle(); reply.recycle(); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 14571defc6fa4..30feae1eeb8bd 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -241,7 +241,7 @@ public interface IActivityManager extends IInterface { public void noteWakeupAlarm(IIntentSender sender) throws RemoteException; - public boolean killPidsForMemory(int[] pids) throws RemoteException; + public boolean killPids(int[] pids, String reason) throws RemoteException; public void reportPss(IApplicationThread caller, int pss) throws RemoteException; @@ -476,7 +476,7 @@ public interface IActivityManager extends IInterface { int GET_PROCESSES_IN_ERROR_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+76; int CLEAR_APP_DATA_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+77; int FORCE_STOP_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+78; - int KILL_PIDS_FOR_MEMORY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+79; + int KILL_PIDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+79; int GET_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+80; int REPORT_PSS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+81; int GET_RUNNING_APP_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+82; diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 399a87dde3a65..c638d04923a2b 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -309,7 +309,7 @@ interface IPackageManager { * MountService uses this to call into the package manager to update * status of sdcard. */ - boolean updateExternalMediaStatus(boolean mounted); + void updateExternalMediaStatus(boolean mounted, boolean reportStatus); String nextPackageToClean(String lastPackage); diff --git a/core/java/android/os/storage/IMountService.aidl b/core/java/android/os/storage/IMountService.aidl index 616c2178b39f4..4862f80d82c69 100644 --- a/core/java/android/os/storage/IMountService.aidl +++ b/core/java/android/os/storage/IMountService.aidl @@ -146,4 +146,10 @@ interface IMountService * Invokes call back once the shutdown is complete. */ void shutdown(IMountShutdownObserver observer); + + /** + * Call into MountService by PackageManager to notify that its done + * processing the media status update request. + */ + void finishMediaUpdate(); } diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index 5bed54948860a..d3ac026d430a3 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -135,17 +135,6 @@ class MountService extends IMountService.Stub private static final int RETRY_UNMOUNT_DELAY = 30; // in ms private static final int MAX_UNMOUNT_RETRIES = 4; - private IntentFilter mPmFilter = new IntentFilter( - Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); - private BroadcastReceiver mPmReceiver = new BroadcastReceiver() { - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) { - mHandler.sendEmptyMessage(H_UNMOUNT_PM_DONE); - } - } - }; - class UnmountCallBack { String path; int retries; @@ -200,49 +189,35 @@ class MountService extends IMountService.Stub class MountServiceHandler extends Handler { ArrayList mForceUnmounts = new ArrayList(); - boolean mRegistered = false; + boolean mUpdatingStatus = false; MountServiceHandler(Looper l) { super(l); } - void registerReceiver() { - mRegistered = true; - if (DEBUG_UNMOUNT) Log.i(TAG, "Registering receiver"); - mContext.registerReceiver(mPmReceiver, mPmFilter); - } - - void unregisterReceiver() { - mRegistered = false; - if (DEBUG_UNMOUNT) Log.i(TAG, "Unregistering receiver"); - mContext.unregisterReceiver(mPmReceiver); - } - public void handleMessage(Message msg) { switch (msg.what) { case H_UNMOUNT_PM_UPDATE: { if (DEBUG_UNMOUNT) Log.i(TAG, "H_UNMOUNT_PM_UPDATE"); UnmountCallBack ucb = (UnmountCallBack) msg.obj; mForceUnmounts.add(ucb); - if (DEBUG_UNMOUNT) Log.i(TAG, " registered = " + mRegistered); + if (DEBUG_UNMOUNT) Log.i(TAG, " registered = " + mUpdatingStatus); // Register only if needed. - if (!mRegistered) { - registerReceiver(); - if (DEBUG_UNMOUNT) Log.i(TAG, "Updating external media status"); - boolean hasExtPkgs = mPms.updateExternalMediaStatus(false); - if (!hasExtPkgs) { - // Unregister right away - mHandler.sendEmptyMessage(H_UNMOUNT_PM_DONE); - } + if (!mUpdatingStatus) { + if (DEBUG_UNMOUNT) Log.i(TAG, "Updating external media status on PackageManager"); + mUpdatingStatus = true; + mPms.updateExternalMediaStatus(false, true); } break; } case H_UNMOUNT_PM_DONE: { if (DEBUG_UNMOUNT) Log.i(TAG, "H_UNMOUNT_PM_DONE"); - // Unregister now. - if (mRegistered) { - unregisterReceiver(); + if (!mUpdatingStatus) { + // Does not correspond to unmount's status update. + return; } + if (DEBUG_UNMOUNT) Log.i(TAG, "Updated status. Processing requests"); + mUpdatingStatus = false; int size = mForceUnmounts.size(); int sizeArr[] = new int[size]; int sizeArrN = 0; @@ -261,7 +236,7 @@ class MountService extends IMountService.Stub ActivityManagerService ams = (ActivityManagerService) ServiceManager.getService("activity"); // Eliminate system process here? - boolean ret = ams.killPidsForMemory(pids); + boolean ret = ams.killPids(pids, "Unmount media"); if (ret) { // Confirm if file references have been freed. pids = getStorageUsers(path); @@ -277,8 +252,8 @@ class MountService extends IMountService.Stub ucb)); } else { if (ucb.retries >= MAX_UNMOUNT_RETRIES) { - Log.i(TAG, "Cannot unmount inspite of " + - MAX_UNMOUNT_RETRIES + " to unmount media"); + Log.i(TAG, "Cannot unmount media inspite of " + + MAX_UNMOUNT_RETRIES + " retries"); // Send final broadcast indicating failure to unmount. } else { mHandler.sendMessageDelayed( @@ -412,9 +387,9 @@ class MountService extends IMountService.Stub } // Update state on PackageManager if (Environment.MEDIA_UNMOUNTED.equals(state)) { - mPms.updateExternalMediaStatus(false); + mPms.updateExternalMediaStatus(false, false); } else if (Environment.MEDIA_MOUNTED.equals(state)) { - mPms.updateExternalMediaStatus(true); + mPms.updateExternalMediaStatus(true, false); } String oldState = mLegacyState; mLegacyState = state; @@ -757,19 +732,15 @@ class MountService extends IMountService.Stub if (!getVolumeState(path).equals(Environment.MEDIA_MOUNTED)) { return VoldResponseCode.OpFailedVolNotMounted; } - - // We unmounted the volume. No of the asec containers are available now. - synchronized (mAsecMountSet) { - mAsecMountSet.clear(); - } - // Notify PackageManager of potential media removal and deal with - // return code later on. The caller of this api should be aware or have been - // notified that the applications installed on the media will be killed. // Redundant probably. But no harm in updating state again. - mPms.updateExternalMediaStatus(false); + mPms.updateExternalMediaStatus(false, false); try { mConnector.doCommand(String.format( "volume unmount %s%s", path, (force ? " force" : ""))); + // We unmounted the volume. None of the asec containers are available now. + synchronized (mAsecMountSet) { + mAsecMountSet.clear(); + } return StorageResultCode.OperationSucceeded; } catch (NativeDaemonConnectorException e) { // Don't worry about mismatch in PackageManager since the @@ -1332,5 +1303,9 @@ class MountService extends IMountService.Stub Log.e(TAG, "Got an empty response"); return ""; } + + public void finishMediaUpdate() { + mHandler.sendEmptyMessage(H_UNMOUNT_PM_DONE); + } } diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 48b3fbbb3a17f..9eb63a65d419c 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -343,6 +343,7 @@ class PackageManagerService extends IPackageManager.Stub { static final int POST_INSTALL = 9; static final int MCS_RECONNECT = 10; static final int MCS_GIVE_UP = 11; + static final int UPDATED_MEDIA_STATUS = 12; // Delay time in millisecs static final int BROADCAST_DELAY = 10 * 1000; @@ -596,6 +597,13 @@ class PackageManagerService extends IPackageManager.Stub { Slog.e(TAG, "Bogus post-install token " + msg.arg1); } } break; + case UPDATED_MEDIA_STATUS: { + try { + PackageHelper.getMountService().finishMediaUpdate(); + } catch (RemoteException e) { + Log.e(TAG, "MountService not running?"); + } + } break; } } } @@ -9373,10 +9381,12 @@ class PackageManagerService extends IPackageManager.Stub { } /* - * Return true if PackageManager does have packages to be updated. + * Update media status on PackageManager. */ - public boolean updateExternalMediaStatus(final boolean mediaStatus) { - final boolean ret; + public void updateExternalMediaStatus(final boolean mediaStatus, final boolean reportStatus) { + if (Binder.getCallingUid() != Process.SYSTEM_UID) { + throw new SecurityException("Media status can only be updated by the system"); + } synchronized (mPackages) { Log.i(TAG, "Updating external media status from " + (mMediaMounted ? "mounted" : "unmounted") + " to " + @@ -9384,32 +9394,29 @@ class PackageManagerService extends IPackageManager.Stub { if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" + mediaStatus+", mMediaMounted=" + mMediaMounted); if (mediaStatus == mMediaMounted) { - return false; + if (reportStatus) { + mHandler.sendEmptyMessage(UPDATED_MEDIA_STATUS); + } + return; } mMediaMounted = mediaStatus; - Set appList = mSettings.findPackagesWithFlag(ApplicationInfo.FLAG_EXTERNAL_STORAGE); - ret = appList != null && appList.size() > 0; - if (DEBUG_SD_INSTALL) { - if (appList != null) { - for (String app : appList) { - Log.i(TAG, "Should enable " + app + " on sdcard"); - } - } - } - if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus returning " + ret); } // Queue up an async operation since the package installation may take a little while. mHandler.post(new Runnable() { public void run() { mHandler.removeCallbacks(this); - updateExternalMediaStatusInner(mediaStatus, ret); + try { + updateExternalMediaStatusInner(mediaStatus); + } finally { + if (reportStatus) { + mHandler.sendEmptyMessage(UPDATED_MEDIA_STATUS); + } + } } }); - return ret; } - private void updateExternalMediaStatusInner(boolean mediaStatus, - boolean sendUpdateBroadcast) { + private void updateExternalMediaStatusInner(boolean mediaStatus) { // If we are up here that means there are packages to be // enabled or disabled. final String list[] = PackageHelper.getSecureContainerList(); @@ -9474,11 +9481,11 @@ class PackageManagerService extends IPackageManager.Stub { // Process packages with valid entries. if (mediaStatus) { if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading packages"); - loadMediaPackages(processCids, uidArr, sendUpdateBroadcast, removeCids); + loadMediaPackages(processCids, uidArr, removeCids); startCleaningPackages(); } else { if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading packages"); - unloadMediaPackages(processCids, uidArr, sendUpdateBroadcast); + unloadMediaPackages(processCids, uidArr); } } @@ -9509,8 +9516,7 @@ class PackageManagerService extends IPackageManager.Stub { * to avoid unnecessary crashes. */ private void loadMediaPackages(HashMap processCids, - int uidArr[], boolean sendUpdateBroadcast, - HashSet removeCids) { + int uidArr[], HashSet removeCids) { ArrayList pkgList = new ArrayList(); Set keys = processCids.keySet(); boolean doGc = false; @@ -9578,7 +9584,7 @@ class PackageManagerService extends IPackageManager.Stub { mSettings.writeLP(); } // Send a broadcast to let everyone know we are done processing - if (sendUpdateBroadcast) { + if (pkgList.size() > 0) { sendResourcesChangedBroadcast(true, pkgList, uidArr); } if (doGc) { @@ -9594,7 +9600,7 @@ class PackageManagerService extends IPackageManager.Stub { } private void unloadMediaPackages(HashMap processCids, - int uidArr[], boolean sendUpdateBroadcast) { + int uidArr[]) { if (DEBUG_SD_INSTALL) Log.i(TAG, "unloading media packages"); ArrayList pkgList = new ArrayList(); ArrayList failedList = new ArrayList(); @@ -9617,7 +9623,7 @@ class PackageManagerService extends IPackageManager.Stub { } } // Send broadcasts - if (sendUpdateBroadcast) { + if (pkgList.size() > 0) { sendResourcesChangedBroadcast(false, pkgList, uidArr); } // Force gc diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index 93e45fc08039a..fdb67f8fe567b 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -10755,7 +10755,7 @@ public class WindowManagerService extends IWindowManager.Stub pids[i] = pidCandidates.keyAt(i); } try { - if (mActivityManager.killPidsForMemory(pids)) { + if (mActivityManager.killPids(pids, "Free memory")) { killedApps = true; } } catch (RemoteException e) { diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 2ecebed86f248..7034c88ae2af2 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -8359,11 +8359,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } - public boolean killPidsForMemory(int[] pids) { + public boolean killPids(int[] pids, String pReason) { if (Binder.getCallingUid() != Process.SYSTEM_UID) { - throw new SecurityException("killPidsForMemory only available to the system"); + throw new SecurityException("killPids only available to the system"); } - + String reason = (pReason == null) ? "Unknown" : pReason; // XXX Note: don't acquire main activity lock here, because the window // manager calls in with its locks held. @@ -8387,7 +8387,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) { worstType = HIDDEN_APP_MIN_ADJ; } - Slog.w(TAG, "Killing processes for memory at adjustment " + worstType); + Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType); for (int i=0; i= worstType) { - Slog.w(TAG, "Killing for memory: " + proc + " (adj " + Slog.w(TAG, "Killing " + reason + " : " + proc + " (adj " + adj + ")"); - EventLog.writeEvent(EventLogTags.AM_KILL_FOR_MEMORY, proc.pid, - proc.processName, adj); + EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid, + proc.processName, adj, reason); killed = true; Process.killProcess(pids[i]); } diff --git a/services/java/com/android/server/am/EventLogTags.logtags b/services/java/com/android/server/am/EventLogTags.logtags index 0ddcc247f77d2..aadd37dc8626a 100644 --- a/services/java/com/android/server/am/EventLogTags.logtags +++ b/services/java/com/android/server/am/EventLogTags.logtags @@ -58,7 +58,7 @@ option java_package com.android.server.am # The activity's onResume has been called. 30022 am_on_resume_called (Component Name|3) # Kill a process to reclaim memory. -30023 am_kill_for_memory (PID|1|5),(Process Name|3),(OomAdj|1|5) +30023 am_kill (PID|1|5),(Process Name|3),(OomAdj|1|5),(Reason|3) # Discard an undelivered serialized broadcast (timeout/ANR/crash) 30024 am_broadcast_discard_filter (Broadcast|1|5),(Action|3),(Receiver Number|1|1),(BroadcastFilter|1|5) 30025 am_broadcast_discard_app (Broadcast|1|5),(Action|3),(Receiver Number|1|1),(App|3) diff --git a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java index dd7a16951de4c..6975c706cd433 100755 --- a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java +++ b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java @@ -93,6 +93,9 @@ public class PackageManagerTests extends AndroidTestCase { protected void setUp() throws Exception { super.setUp(); mOrigState = getMediaState(); + if (!mountMedia()) { + Log.i(TAG, "sdcard not mounted? Some of these tests might fail"); + } } @Override