diff options
12 files changed, 319 insertions, 66 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 13add09bbaaf..9cd42a5eb9fd 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -5719,14 +5719,18 @@ public final class ActivityThread extends ClientTransactionHandler { if (packages == null) { break; } + + List<String> packagesHandled = new ArrayList<>(); + synchronized (mResourcesManager) { for (int i = packages.length - 1; i >= 0; i--) { - WeakReference<LoadedApk> ref = mPackages.get(packages[i]); + String packageName = packages[i]; + WeakReference<LoadedApk> ref = mPackages.get(packageName); LoadedApk pkgInfo = ref != null ? ref.get() : null; if (pkgInfo != null) { hasPkgInfo = true; } else { - ref = mResourcePackages.get(packages[i]); + ref = mResourcePackages.get(packageName); pkgInfo = ref != null ? ref.get() : null; if (pkgInfo != null) { hasPkgInfo = true; @@ -5737,8 +5741,8 @@ public final class ActivityThread extends ClientTransactionHandler { // Adjust it's internal references to the application info and // resources. if (pkgInfo != null) { + packagesHandled.add(packageName); try { - final String packageName = packages[i]; final ApplicationInfo aInfo = sPackageManager.getApplicationInfo( packageName, @@ -5770,6 +5774,13 @@ public final class ActivityThread extends ClientTransactionHandler { } } } + + try { + getPackageManager().notifyPackagesReplacedReceived( + packagesHandled.toArray(new String[0])); + } catch (RemoteException ignored) { + } + break; } } diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index cf704d52cba0..6ab4657d727d 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -770,4 +770,6 @@ interface IPackageManager { int getRuntimePermissionsVersion(int userId); void setRuntimePermissionsVersion(int version, int userId); + + void notifyPackagesReplacedReceived(in String[] packages); } diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index a51a871e7780..232869d7aefc 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -453,14 +453,22 @@ public class GraphicsEnvironment { final boolean appIsProfileable = isProfileable(context); final boolean deviceIsDebuggable = getCanLoadSystemLibraries() == 1; if (appIsDebuggable || appIsProfileable || deviceIsDebuggable) { - - String debugPackage = - coreSettings.getString(Settings.Global.GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE); + String debugPackage; + + if (coreSettings != null) { + debugPackage = + coreSettings.getString(Settings.Global.GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE); + } else { + ContentResolver contentResolver = context.getContentResolver(); + debugPackage = Settings.Global.getString(contentResolver, + Settings.Global.GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE); + } if ((debugPackage != null) && (!debugPackage.isEmpty())) { return debugPackage; } } + return ""; } diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 3410d8d86852..44fc45e13218 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -88,6 +88,7 @@ import android.util.ArraySet; import android.util.EventLog; import android.util.Log; import android.util.Slog; +import android.util.TimeUtils; import com.android.internal.annotations.GuardedBy; import com.android.internal.content.PackageMonitor; @@ -3567,6 +3568,10 @@ public class LocationManagerService extends ILocationManager.Stub { return; } pw.println("Current Location Manager state:"); + pw.print(" Current System Time: " + + TimeUtils.logTimeOfDay(System.currentTimeMillis())); + pw.println(", Current Elapsed Time: " + + TimeUtils.formatDuration(SystemClock.elapsedRealtime())); pw.println(" Current user: " + mCurrentUserId + " " + Arrays.toString( mCurrentUserProfiles)); pw.println(" Location mode: " + isLocationEnabled()); diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 1bcc4c8a6d08..a93f2187db08 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -3172,15 +3172,28 @@ public final class ProcessList { @GuardedBy("mService") void sendPackageBroadcastLocked(int cmd, String[] packages, int userId) { + boolean foundProcess = false; for (int i = mLruProcesses.size() - 1; i >= 0; i--) { ProcessRecord r = mLruProcesses.get(i); if (r.thread != null && (userId == UserHandle.USER_ALL || r.userId == userId)) { try { + for (int index = packages.length - 1; index >= 0 && !foundProcess; index--) { + if (packages[index].equals(r.info.packageName)) { + foundProcess = true; + } + } r.thread.dispatchPackageBroadcast(cmd, packages); } catch (RemoteException ex) { } } } + + if (!foundProcess) { + try { + AppGlobals.getPackageManager().notifyPackagesReplacedReceived(packages); + } catch (RemoteException ignored) { + } + } } /** Returns the uid's process state or PROCESS_STATE_NONEXISTENT if not running */ diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index c573332235d8..4ce6d91d25b0 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -43,7 +43,6 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; -import java.util.ArrayList; /** @hide */ /*package*/ final class AudioDeviceBroker { @@ -376,24 +375,29 @@ import java.util.ArrayList; mAudioService.postAccessoryPlugMediaUnmute(device); } - /*package*/ AudioService.VolumeStreamState getStreamState(int streamType) { - return mAudioService.getStreamState(streamType); + /*package*/ int getVssVolumeForDevice(int streamType, int device) { + return mAudioService.getVssVolumeForDevice(streamType, device); } - /*package*/ ArrayList<AudioService.SetModeDeathHandler> getSetModeDeathHandlers() { - return mAudioService.mSetModeDeathHandlers; + /*package*/ int getModeOwnerPid() { + return mAudioService.getModeOwnerPid(); } /*package*/ int getDeviceForStream(int streamType) { return mAudioService.getDeviceForStream(streamType); } - /*package*/ void setDeviceVolume(AudioService.VolumeStreamState streamState, int device) { - mAudioService.setDeviceVolume(streamState, device); + /*package*/ void postApplyVolumeOnDevice(int streamType, int device, String caller) { + mAudioService.postApplyVolumeOnDevice(streamType, device, caller); } - /*packages*/ void observeDevicesForAllStreams() { - mAudioService.observeDevicesForAllStreams(); + /*package*/ void postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device, + String caller) { + mAudioService.postSetVolumeIndexOnDevice(streamType, vssVolIndex, device, caller); + } + + /*packages*/ void postObserveDevicesForAllStreams() { + mAudioService.postObserveDevicesForAllStreams(); } /*package*/ boolean isInCommunication() { diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java index 91b51b4989d8..f9dbdd5b13db 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java +++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java @@ -198,14 +198,10 @@ public final class AudioDeviceInventory { } } if (a2dpVolume != -1) { - AudioService.VolumeStreamState streamState = - mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC); - // Convert index to internal representation in VolumeStreamState - a2dpVolume = a2dpVolume * 10; - streamState.setIndex(a2dpVolume, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, - "onSetA2dpSinkConnectionState"); - mDeviceBroker.setDeviceVolume( - streamState, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP); + mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC, + // convert index to internal representation in VolumeStreamState + a2dpVolume * 10, + AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, "onSetA2dpSinkConnectionState"); } makeA2dpDeviceAvailable(address, BtHelper.getName(btDevice), "onSetA2dpSinkConnectionState", a2dpCodec); @@ -302,14 +298,11 @@ public final class AudioDeviceInventory { if (event == BtHelper.EVENT_ACTIVE_DEVICE_CHANGE) { // Device is connected if (a2dpVolume != -1) { - final AudioService.VolumeStreamState streamState = - mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC); - // Convert index to internal representation in VolumeStreamState - a2dpVolume = a2dpVolume * 10; - streamState.setIndex(a2dpVolume, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, + mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC, + // convert index to internal representation in VolumeStreamState + a2dpVolume * 10, + AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, "onBluetoothA2dpActiveDeviceChange"); - mDeviceBroker.setDeviceVolume( - streamState, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP); } } else if (event == BtHelper.EVENT_DEVICE_CONFIG_CHANGE) { if (di.mDeviceCodecFormat != a2dpCodec) { @@ -352,7 +345,7 @@ public final class AudioDeviceInventory { } } mRoutesObservers.finishBroadcast(); - mDeviceBroker.observeDevicesForAllStreams(); + mDeviceBroker.postObserveDevicesForAllStreams(); } private static final int DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG = @@ -655,8 +648,6 @@ public final class AudioDeviceInventory { int a2dpCodec) { // enable A2DP before notifying A2DP connection to avoid unnecessary processing in // audio policy manager - AudioService.VolumeStreamState streamState = - mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC); mDeviceBroker.setBluetoothA2dpOnInt(true, eventSource); AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, AudioSystem.DEVICE_STATE_AVAILABLE, address, name, a2dpCodec); @@ -727,8 +718,8 @@ public final class AudioDeviceInventory { @GuardedBy("mConnectedDevices") private void makeHearingAidDeviceAvailable(String address, String name, String eventSource) { - final int hearingAidVolIndex = mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC) - .getIndex(AudioSystem.DEVICE_OUT_HEARING_AID); + final int hearingAidVolIndex = mDeviceBroker.getVssVolumeForDevice(AudioSystem.STREAM_MUSIC, + AudioSystem.DEVICE_OUT_HEARING_AID); mDeviceBroker.postSetHearingAidVolumeIndex(hearingAidVolIndex, AudioSystem.STREAM_MUSIC); AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID, @@ -739,9 +730,8 @@ public final class AudioDeviceInventory { new DeviceInfo(AudioSystem.DEVICE_OUT_HEARING_AID, name, address, AudioSystem.AUDIO_FORMAT_DEFAULT)); mDeviceBroker.postAccessoryPlugMediaUnmute(AudioSystem.DEVICE_OUT_HEARING_AID); - mDeviceBroker.setDeviceVolume( - mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC), - AudioSystem.DEVICE_OUT_HEARING_AID); + mDeviceBroker.postApplyVolumeOnDevice(AudioSystem.STREAM_MUSIC, + AudioSystem.DEVICE_OUT_HEARING_AID, "makeHearingAidDeviceAvailable"); setCurrentAudioRouteNameIfPossible(name); } diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 2d00f298e25e..b6879a3def03 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -258,6 +258,8 @@ public class AudioService extends IAudioService.Stub private static final int MSG_DISPATCH_AUDIO_SERVER_STATE = 23; private static final int MSG_ENABLE_SURROUND_FORMATS = 24; private static final int MSG_UPDATE_RINGER_MODE = 25; + private static final int MSG_SET_DEVICE_STREAM_VOLUME = 26; + private static final int MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS = 27; // start of messages handled under wakelock // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(), // and not with sendMsg(..., ..., SENDMSG_QUEUE, ...) @@ -274,8 +276,8 @@ public class AudioService extends IAudioService.Stub /** @see VolumeStreamState */ private VolumeStreamState[] mStreamStates; - /*package*/ VolumeStreamState getStreamState(int stream) { - return mStreamStates[stream]; + /*package*/ int getVssVolumeForDevice(int stream, int device) { + return mStreamStates[stream].getIndex(device); } private SettingsObserver mSettingsObserver; @@ -2936,7 +2938,21 @@ public class AudioService extends IAudioService.Stub } - /*package*/ class SetModeDeathHandler implements IBinder.DeathRecipient { + /** + * Return the pid of the current audio mode owner + * @return 0 if nobody owns the mode + */ + /*package*/ int getModeOwnerPid() { + int modeOwnerPid = 0; + try { + modeOwnerPid = mSetModeDeathHandlers.get(0).getPid(); + } catch (Exception e) { + // nothing to do, modeOwnerPid is not modified + } + return modeOwnerPid; + } + + private class SetModeDeathHandler implements IBinder.DeathRecipient { private IBinder mCb; // To be notified of client's death private int mPid; private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client @@ -4096,8 +4112,14 @@ public class AudioService extends IAudioService.Stub } } + /*package*/ void postObserveDevicesForAllStreams() { + sendMsg(mAudioHandler, + MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS, + SENDMSG_QUEUE, 0 /*arg1*/, 0 /*arg2*/, null /*obj*/, + 0 /*delay*/); + } - /*package*/ void observeDevicesForAllStreams() { + private void onObserveDevicesForAllStreams() { observeDevicesForStreams(-1); } @@ -4270,7 +4292,7 @@ public class AudioService extends IAudioService.Stub // 2 mSetModeLock // 3 mSettingsLock // 4 VolumeStreamState.class - public class VolumeStreamState { + private class VolumeStreamState { private final int mStreamType; private int mIndexMin; private int mIndexMax; @@ -4740,6 +4762,74 @@ public class AudioService extends IAudioService.Stub } } + private static final class DeviceVolumeUpdate { + final int mStreamType; + final int mDevice; + final @NonNull String mCaller; + private static final int NO_NEW_INDEX = -2049; + private final int mVssVolIndex; + + // Constructor with volume index, meant to cause this volume to be set and applied for the + // given stream type on the given device + DeviceVolumeUpdate(int streamType, int vssVolIndex, int device, @NonNull String caller) { + mStreamType = streamType; + mVssVolIndex = vssVolIndex; + mDevice = device; + mCaller = caller; + } + + // Constructor with no volume index, meant to cause re-apply of volume for the given + // stream type on the given device + DeviceVolumeUpdate(int streamType, int device, @NonNull String caller) { + mStreamType = streamType; + mVssVolIndex = NO_NEW_INDEX; + mDevice = device; + mCaller = caller; + } + + boolean hasVolumeIndex() { + return mVssVolIndex != NO_NEW_INDEX; + } + + int getVolumeIndex() throws IllegalStateException { + Preconditions.checkState(mVssVolIndex != NO_NEW_INDEX); + return mVssVolIndex; + } + } + + /*package*/ void postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device, + String caller) { + sendMsg(mAudioHandler, + MSG_SET_DEVICE_STREAM_VOLUME, + SENDMSG_QUEUE, 0 /*arg1*/, 0 /*arg2*/, + new DeviceVolumeUpdate(streamType, vssVolIndex, device, caller), + 0 /*delay*/); + } + + /*package*/ void postApplyVolumeOnDevice(int streamType, int device, @NonNull String caller) { + sendMsg(mAudioHandler, + MSG_SET_DEVICE_STREAM_VOLUME, + SENDMSG_QUEUE, 0 /*arg1*/, 0 /*arg2*/, + new DeviceVolumeUpdate(streamType, device, caller), + 0 /*delay*/); + } + + private void onSetVolumeIndexOnDevice(@NonNull DeviceVolumeUpdate update) { + synchronized (VolumeStreamState.class) { + final VolumeStreamState streamState = mStreamStates[update.mStreamType]; + if (update.hasVolumeIndex()) { + final int index = update.getVolumeIndex(); + streamState.setIndex(index, update.mDevice, update.mCaller); + sVolumeLogger.log(new AudioEventLogger.StringEvent(update.mCaller + " dev:0x" + + Integer.toHexString(update.mDevice) + " volIdx:" + index)); + } else { + sVolumeLogger.log(new AudioEventLogger.StringEvent(update.mCaller + + " update vol on dev:0x" + Integer.toHexString(update.mDevice))); + } + setDeviceVolume(streamState, update.mDevice); + } + } + /*package*/ void setDeviceVolume(VolumeStreamState streamState, int device) { final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported(); @@ -5180,6 +5270,14 @@ public class AudioService extends IAudioService.Stub case MSG_UPDATE_RINGER_MODE: onUpdateRingerModeServiceInt(); break; + + case MSG_SET_DEVICE_STREAM_VOLUME: + onSetVolumeIndexOnDevice((DeviceVolumeUpdate) msg.obj); + break; + + case MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS: + onObserveDevicesForAllStreams(); + break; } } } diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java index 332ff362392a..068c3d8a1264 100644 --- a/services/core/java/com/android/server/audio/BtHelper.java +++ b/services/core/java/com/android/server/audio/BtHelper.java @@ -765,8 +765,7 @@ public class BtHelper { broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING); // Accept SCO audio activation only in NORMAL audio mode or if the mode is // currently controlled by the same client process. - int modeOwnerPid = mDeviceBroker.getSetModeDeathHandlers().isEmpty() - ? 0 : mDeviceBroker.getSetModeDeathHandlers().get(0).getPid(); + final int modeOwnerPid = mDeviceBroker.getModeOwnerPid(); if (modeOwnerPid != 0 && (modeOwnerPid != mCreatorPid)) { Log.w(TAG, "requestScoState: audio mode is not NORMAL and modeOwnerPid " + modeOwnerPid + " != creatorPid " + mCreatorPid); diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java index 96fc6ec5907c..ff0af1324222 100644 --- a/services/core/java/com/android/server/location/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/GnssLocationProvider.java @@ -66,6 +66,7 @@ import android.telephony.gsm.GsmCellLocation; import android.text.TextUtils; import android.util.Log; import android.util.StatsLog; +import android.util.TimeUtils; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IBatteryStats; @@ -332,9 +333,16 @@ public class GnssLocationProvider extends AbstractLocationProvider implements // true if low power mode for the GNSS chipset is part of the latest request. private boolean mLowPowerMode = false; - // true if we started navigation + // true if we started navigation in the HAL, only change value of this in setStarted private boolean mStarted; + // for logging of latest change, and warning of ongoing location after a stop + private long mStartedChangedElapsedRealtime; + + // threshold for delay in GNSS engine turning off before warning & error + private static final long LOCATION_OFF_DELAY_THRESHOLD_WARN_MILLIS = 2 * 1000; + private static final long LOCATION_OFF_DELAY_THRESHOLD_ERROR_MILLIS = 15 * 1000; + // capabilities reported through the top level IGnssCallback.hal private volatile int mTopHalCapabilities; @@ -1192,7 +1200,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements if (DEBUG) Log.d(TAG, "startNavigating"); mTimeToFirstFix = 0; mLastFixTime = 0; - mStarted = true; + setStarted(true); mPositionMode = GPS_POSITION_MODE_STANDALONE; // Notify about suppressed output, if speed limit was previously exceeded. // Elsewhere, we check again with every speed output reported. @@ -1230,12 +1238,12 @@ public class GnssLocationProvider extends AbstractLocationProvider implements mLowPowerMode = mProviderRequest.lowPowerMode; if (!setPositionMode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC, interval, 0, 0, mLowPowerMode)) { - mStarted = false; + setStarted(false); Log.e(TAG, "set_position_mode failed in startNavigating()"); return; } if (!native_start()) { - mStarted = false; + setStarted(false); Log.e(TAG, "native_start failed in startNavigating()"); return; } @@ -1258,7 +1266,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private void stopNavigating() { if (DEBUG) Log.d(TAG, "stopNavigating"); if (mStarted) { - mStarted = false; + setStarted(false); native_stop(); mLastFixTime = 0; // native_stop() may reset the position mode in hardware. @@ -1270,6 +1278,13 @@ public class GnssLocationProvider extends AbstractLocationProvider implements } } + private void setStarted(boolean started) { + if (mStarted != started) { + mStarted = started; + mStartedChangedElapsedRealtime = SystemClock.elapsedRealtime(); + } + } + private void hibernate() { // stop GPS until our next fix interval arrives stopNavigating(); @@ -1319,6 +1334,21 @@ public class GnssLocationProvider extends AbstractLocationProvider implements mGnssMetrics.logMissedReports(mFixInterval, timeBetweenFixes); } } + } else { + // Warn or error about long delayed GNSS engine shutdown as this generally wastes + // power and sends location when not expected. + long locationAfterStartedFalseMillis = + SystemClock.elapsedRealtime() - mStartedChangedElapsedRealtime; + if (locationAfterStartedFalseMillis > LOCATION_OFF_DELAY_THRESHOLD_WARN_MILLIS) { + String logMessage = "Unexpected GNSS Location report " + + TimeUtils.formatDuration(locationAfterStartedFalseMillis) + + " after location turned off"; + if (locationAfterStartedFalseMillis > LOCATION_OFF_DELAY_THRESHOLD_ERROR_MILLIS) { + Log.e(TAG, logMessage); + } else { + Log.w(TAG, logMessage); + } + } } mLastFixTime = SystemClock.elapsedRealtime(); @@ -1538,7 +1568,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private void restartLocationRequest() { if (DEBUG) Log.d(TAG, "restartLocationRequest"); - mStarted = false; + setStarted(false); updateRequirements(); } @@ -2152,7 +2182,10 @@ public class GnssLocationProvider extends AbstractLocationProvider implements @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { StringBuilder s = new StringBuilder(); - s.append(" mStarted=").append(mStarted).append('\n'); + s.append(" mStarted=").append(mStarted).append(" (changed "); + TimeUtils.formatDuration(SystemClock.elapsedRealtime() + - mStartedChangedElapsedRealtime, s); + s.append(" ago)").append('\n'); s.append(" mFixInterval=").append(mFixInterval).append('\n'); s.append(" mLowPowerMode=").append(mLowPowerMode).append('\n'); s.append(" mGnssMeasurementsProvider.isRegistered()=") diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index c4d4106804e1..3c336eac1ae6 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -952,6 +952,9 @@ public class PackageManagerService extends IPackageManager.Stub ActivityInfo mInstantAppInstallerActivity; final ResolveInfo mInstantAppInstallerInfo = new ResolveInfo(); + private final Map<String, Pair<PackageInstalledInfo, IPackageInstallObserver2>> + mNoKillInstallObservers = Collections.synchronizedMap(new HashMap<>()); + final SparseArray<IntentFilterVerificationState> mIntentFilterVerificationStates = new SparseArray<>(); @@ -1319,6 +1322,11 @@ public class PackageManagerService extends IPackageManager.Stub static final int INSTANT_APP_RESOLUTION_PHASE_TWO = 20; static final int ENABLE_ROLLBACK_STATUS = 21; static final int ENABLE_ROLLBACK_TIMEOUT = 22; + static final int DEFERRED_NO_KILL_POST_DELETE = 23; + static final int DEFERRED_NO_KILL_INSTALL_OBSERVER = 24; + + static final int DEFERRED_NO_KILL_POST_DELETE_DELAY_MS = 3 * 1000; + static final int DEFERRED_NO_KILL_INSTALL_OBSERVER_DELAY_MS = 500; static final int WRITE_SETTINGS_DELAY = 10*1000; // 10 seconds @@ -1525,6 +1533,20 @@ public class PackageManagerService extends IPackageManager.Stub Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "postInstall", msg.arg1); } break; + case DEFERRED_NO_KILL_POST_DELETE: { + synchronized (mInstallLock) { + InstallArgs args = (InstallArgs) msg.obj; + if (args != null) { + args.doPostDeleteLI(true); + } + } + } break; + case DEFERRED_NO_KILL_INSTALL_OBSERVER: { + String packageName = (String) msg.obj; + if (packageName != null) { + notifyInstallObserver(packageName); + } + } break; case WRITE_SETTINGS: { Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); synchronized (mPackages) { @@ -1791,7 +1813,10 @@ public class PackageManagerService extends IPackageManager.Stub String[] grantedPermissions, List<String> whitelistedRestrictedPermissions, boolean launchedForRestore, String installerPackage, IPackageInstallObserver2 installObserver) { - if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { + final boolean succeeded = res.returnCode == PackageManager.INSTALL_SUCCEEDED; + final boolean update = res.removedInfo != null && res.removedInfo.removedPackage != null; + + if (succeeded) { // Send the removed broadcasts if (res.removedInfo != null) { res.removedInfo.sendPackageRemovedBroadcasts(killApp); @@ -1819,8 +1844,6 @@ public class PackageManagerService extends IPackageManager.Stub mPermissionCallback); } - final boolean update = res.removedInfo != null - && res.removedInfo.removedPackage != null; final String installerPackageName = res.installerPackageName != null ? res.installerPackageName @@ -2029,11 +2052,18 @@ public class PackageManagerService extends IPackageManager.Stub getUnknownSourcesSettings()); // Remove the replaced package's older resources safely now - // We delete after a gc for applications on sdcard. - if (res.removedInfo != null && res.removedInfo.args != null) { - Runtime.getRuntime().gc(); - synchronized (mInstallLock) { - res.removedInfo.args.doPostDeleteLI(true); + InstallArgs args = res.removedInfo != null ? res.removedInfo.args : null; + if (args != null) { + if (!killApp) { + // If we didn't kill the app, defer the deletion of code/resource files, since + // they may still be in use by the running application. This mitigates problems + // in cases where resources or code is loaded by a new Activity before + // ApplicationInfo changes have propagated to all application threads. + scheduleDeferredNoKillPostDelete(args); + } else { + synchronized (mInstallLock) { + args.doPostDeleteLI(true); + } } } else { // Force a gc to clear up things. Ask for a background one, it's fine to go on @@ -2056,18 +2086,62 @@ public class PackageManagerService extends IPackageManager.Stub } } - // If someone is watching installs - notify them + final boolean deferInstallObserver = succeeded && update && !killApp; + if (deferInstallObserver) { + scheduleDeferredNoKillInstallObserver(res, installObserver); + } else { + notifyInstallObserver(res, installObserver); + } + } + + @Override + public void notifyPackagesReplacedReceived(String[] packages) { + final int callingUid = Binder.getCallingUid(); + final int callingUserId = UserHandle.getUserId(callingUid); + + for (String packageName : packages) { + PackageSetting setting = mSettings.mPackages.get(packageName); + if (setting != null && filterAppAccessLPr(setting, callingUid, callingUserId)) { + notifyInstallObserver(packageName); + } + } + } + + private void notifyInstallObserver(String packageName) { + Pair<PackageInstalledInfo, IPackageInstallObserver2> pair = + mNoKillInstallObservers.remove(packageName); + + if (pair != null) { + notifyInstallObserver(pair.first, pair.second); + } + } + + private void notifyInstallObserver(PackageInstalledInfo info, + IPackageInstallObserver2 installObserver) { if (installObserver != null) { try { - Bundle extras = extrasForInstallResult(res); - installObserver.onPackageInstalled(res.name, res.returnCode, - res.returnMsg, extras); + Bundle extras = extrasForInstallResult(info); + installObserver.onPackageInstalled(info.name, info.returnCode, + info.returnMsg, extras); } catch (RemoteException e) { Slog.i(TAG, "Observer no longer exists."); } } } + private void scheduleDeferredNoKillPostDelete(InstallArgs args) { + Message message = mHandler.obtainMessage(DEFERRED_NO_KILL_POST_DELETE, args); + mHandler.sendMessageDelayed(message, DEFERRED_NO_KILL_POST_DELETE_DELAY_MS); + } + + private void scheduleDeferredNoKillInstallObserver(PackageInstalledInfo info, + IPackageInstallObserver2 observer) { + String packageName = info.pkg.packageName; + mNoKillInstallObservers.put(packageName, Pair.create(info, observer)); + Message message = mHandler.obtainMessage(DEFERRED_NO_KILL_INSTALL_OBSERVER, packageName); + mHandler.sendMessageDelayed(message, DEFERRED_NO_KILL_INSTALL_OBSERVER_DELAY_MS); + } + /** * Gets the type of the external storage a package is installed on. * @param packageVolume The storage volume of the package. diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index db2fba97f4ac..2a9cb8998cac 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -2687,7 +2687,7 @@ public final class Settings { private void writePackageListLPrInternal(int creatingUserId) { // Only derive GIDs for active users (not dying) - final List<UserInfo> users = UserManagerService.getInstance().getUsers(true); + final List<UserInfo> users = getUsers(UserManagerService.getInstance(), true); int[] userIds = new int[users.size()]; for (int i = 0; i < userIds.length; i++) { userIds[i] = users.get(i).id; @@ -4357,10 +4357,26 @@ public final class Settings { return pkgSetting.getHarmfulAppWarning(userId); } + /** + * Return all users on the device, including partial or dying users. + * @param userManager UserManagerService instance + * @return the list of users + */ private static List<UserInfo> getAllUsers(UserManagerService userManager) { + return getUsers(userManager, false); + } + + /** + * Return the list of users on the device. Clear the calling identity before calling into + * UserManagerService. + * @param userManager UserManagerService instance + * @param excludeDying Indicates whether to exclude any users marked for deletion. + * @return the list of users + */ + private static List<UserInfo> getUsers(UserManagerService userManager, boolean excludeDying) { long id = Binder.clearCallingIdentity(); try { - return userManager.getUsers(false); + return userManager.getUsers(excludeDying); } catch (NullPointerException npe) { // packagemanager not yet initialized } finally { |