diff options
Diffstat (limited to 'services')
32 files changed, 1436 insertions, 452 deletions
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index 96063d5..c14ed8b 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -656,12 +656,19 @@ class AlarmManagerService extends SystemService { } @Override - public void setTime(long millis) { + public boolean setTime(long millis) { getContext().enforceCallingOrSelfPermission( "android.permission.SET_TIME", "setTime"); - SystemClock.setCurrentTimeMillis(millis); + if (mNativeData == 0) { + Slog.w(TAG, "Not setting time since no alarm driver is available."); + return false; + } + + synchronized (mLock) { + return setKernelTime(mNativeData, millis) == 0; + } } @Override @@ -1039,6 +1046,7 @@ class AlarmManagerService extends SystemService { private native void close(long nativeData); private native void set(long nativeData, int type, long seconds, long nanoseconds); private native int waitForAlarm(long nativeData); + private native int setKernelTime(long nativeData, long millis); private native int setKernelTimezone(long nativeData, int minuteswest); void triggerAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED, long nowRTC) { diff --git a/services/core/java/com/android/server/AssetAtlasService.java b/services/core/java/com/android/server/AssetAtlasService.java index 3fb006b..fc4838c 100644 --- a/services/core/java/com/android/server/AssetAtlasService.java +++ b/services/core/java/com/android/server/AssetAtlasService.java @@ -114,12 +114,11 @@ public class AssetAtlasService extends IAssetAtlas.Stub { // Describes how bitmaps are placed in the atlas. Each bitmap is // represented by several entries in the array: - // int0: SkBitmap*, the native bitmap object - // int1: x position - // int2: y position - // int3: rotated, 1 if the bitmap must be rotated, 0 otherwise - // NOTE: This will need to be handled differently to support 64 bit pointers - private int[] mAtlasMap; + // long0: SkBitmap*, the native bitmap object + // long1: x position + // long2: y position + // long3: rotated, 1 if the bitmap must be rotated, 0 otherwise + private long[] mAtlasMap; /** * Creates a new service. Upon creating, the service will gather the list of @@ -196,7 +195,7 @@ public class AssetAtlasService extends IAssetAtlas.Stub { private final ArrayList<Bitmap> mBitmaps; private final int mPixelCount; - private int mNativeBitmap; + private long mNativeBitmap; // Used for debugging only private Bitmap mAtlasBitmap; @@ -260,8 +259,8 @@ public class AssetAtlasService extends IAssetAtlas.Stub { final Atlas.Entry entry = new Atlas.Entry(); - mAtlasMap = new int[packCount * ATLAS_MAP_ENTRY_FIELD_COUNT]; - int[] atlasMap = mAtlasMap; + mAtlasMap = new long[packCount * ATLAS_MAP_ENTRY_FIELD_COUNT]; + long[] atlasMap = mAtlasMap; int mapIndex = 0; boolean result = false; @@ -288,8 +287,7 @@ public class AssetAtlasService extends IAssetAtlas.Stub { } canvas.drawBitmap(bitmap, 0.0f, 0.0f, null); canvas.restore(); - // TODO: Change mAtlasMap to long[] to support 64-bit systems - atlasMap[mapIndex++] = (int) bitmap.mNativeBitmap; + atlasMap[mapIndex++] = bitmap.mNativeBitmap; atlasMap[mapIndex++] = entry.x; atlasMap[mapIndex++] = entry.y; atlasMap[mapIndex++] = entry.rotated ? 1 : 0; @@ -365,9 +363,9 @@ public class AssetAtlasService extends IAssetAtlas.Stub { } } - private static native int nAcquireAtlasCanvas(Canvas canvas, int width, int height); - private static native void nReleaseAtlasCanvas(Canvas canvas, int bitmap); - private static native boolean nUploadAtlas(GraphicBuffer buffer, int bitmap); + private static native long nAcquireAtlasCanvas(Canvas canvas, int width, int height); + private static native void nReleaseAtlasCanvas(Canvas canvas, long bitmap); + private static native boolean nUploadAtlas(GraphicBuffer buffer, long bitmap); @Override public boolean isCompatible(int ppid) { @@ -380,7 +378,7 @@ public class AssetAtlasService extends IAssetAtlas.Stub { } @Override - public int[] getMap() throws RemoteException { + public long[] getMap() throws RemoteException { return mAtlasReady.get() ? mAtlasMap : null; } diff --git a/services/core/java/com/android/server/ConsumerIrService.java b/services/core/java/com/android/server/ConsumerIrService.java index 783dff1..583f1bc 100644 --- a/services/core/java/com/android/server/ConsumerIrService.java +++ b/services/core/java/com/android/server/ConsumerIrService.java @@ -49,13 +49,13 @@ public class ConsumerIrService extends IConsumerIrService.Stub { private static final int MAX_XMIT_TIME = 2000000; /* in microseconds */ - private static native int halOpen(); - private static native int halTransmit(int halObject, int carrierFrequency, int[] pattern); - private static native int[] halGetCarrierFrequencies(int halObject); + private static native long halOpen(); + private static native int halTransmit(long halObject, int carrierFrequency, int[] pattern); + private static native int[] halGetCarrierFrequencies(long halObject); private final Context mContext; private final PowerManager.WakeLock mWakeLock; - private final int mHal; + private final long mNativeHal; private final Object mHalLock = new Object(); ConsumerIrService(Context context) { @@ -65,23 +65,23 @@ public class ConsumerIrService extends IConsumerIrService.Stub { mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); mWakeLock.setReferenceCounted(true); - mHal = halOpen(); + mNativeHal = halOpen(); if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CONSUMER_IR)) { - if (mHal == 0) { + if (mNativeHal == 0) { throw new RuntimeException("FEATURE_CONSUMER_IR present, but no IR HAL loaded!"); } - } else if (mHal != 0) { + } else if (mNativeHal != 0) { throw new RuntimeException("IR HAL present, but FEATURE_CONSUMER_IR is not set!"); } } @Override public boolean hasIrEmitter() { - return mHal != 0; + return mNativeHal != 0; } private void throwIfNoIrEmitter() { - if (mHal == 0) { + if (mNativeHal == 0) { throw new UnsupportedOperationException("IR emitter not available"); } } @@ -111,7 +111,7 @@ public class ConsumerIrService extends IConsumerIrService.Stub { // Right now there is no mechanism to ensure fair queing of IR requests synchronized (mHalLock) { - int err = halTransmit(mHal, carrierFrequency, pattern); + int err = halTransmit(mNativeHal, carrierFrequency, pattern); if (err < 0) { Slog.e(TAG, "Error transmitting: " + err); @@ -129,7 +129,7 @@ public class ConsumerIrService extends IConsumerIrService.Stub { throwIfNoIrEmitter(); synchronized(mHalLock) { - return halGetCarrierFrequencies(mHal); + return halGetCarrierFrequencies(mNativeHal); } } } diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index eebd1c5..e0b568b 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -452,6 +452,9 @@ public class LocationManagerService extends ILocationManager.Stub { * @param userId the new active user's UserId */ private void switchUser(int userId) { + if (mCurrentUserId == userId) { + return; + } mBlacklist.switchUser(userId); mLocationHandler.removeMessages(MSG_LOCATION_CHANGED); synchronized (mLock) { diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index 816ae69..f73a92b 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -91,6 +91,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -384,18 +385,37 @@ class MountService extends IMountService.Stub } class ShutdownCallBack extends UnmountCallBack { - IMountShutdownObserver observer; - ShutdownCallBack(String path, IMountShutdownObserver observer) { + MountShutdownLatch mMountShutdownLatch; + ShutdownCallBack(String path, final MountShutdownLatch mountShutdownLatch) { super(path, true, false); - this.observer = observer; + mMountShutdownLatch = mountShutdownLatch; } @Override void handleFinished() { int ret = doUnmountVolume(path, true, removeEncryption); - if (observer != null) { + Slog.i(TAG, "Unmount completed: " + path + ", result code: " + ret); + mMountShutdownLatch.countDown(); + } + } + + static class MountShutdownLatch { + private IMountShutdownObserver mObserver; + private AtomicInteger mCount; + + MountShutdownLatch(final IMountShutdownObserver observer, int count) { + mObserver = observer; + mCount = new AtomicInteger(count); + } + + void countDown() { + boolean sendShutdown = false; + if (mCount.decrementAndGet() == 0) { + sendShutdown = true; + } + if (sendShutdown && mObserver != null) { try { - observer.onShutDownComplete(ret); + mObserver.onShutDownComplete(StorageResultCode.OperationSucceeded); } catch (RemoteException e) { Slog.w(TAG, "RemoteException when shutting down"); } @@ -1426,6 +1446,10 @@ class MountService extends IMountService.Stub Slog.i(TAG, "Shutting down"); synchronized (mVolumesLock) { + // Get all volumes to be unmounted. + MountShutdownLatch mountShutdownLatch = new MountShutdownLatch(observer, + mVolumeStates.size()); + for (String path : mVolumeStates.keySet()) { String state = mVolumeStates.get(path); @@ -1461,19 +1485,16 @@ class MountService extends IMountService.Stub if (state.equals(Environment.MEDIA_MOUNTED)) { // Post a unmount message. - ShutdownCallBack ucb = new ShutdownCallBack(path, observer); + ShutdownCallBack ucb = new ShutdownCallBack(path, mountShutdownLatch); mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_PM_UPDATE, ucb)); } else if (observer != null) { /* - * Observer is waiting for onShutDownComplete when we are done. - * Since nothing will be done send notification directly so shutdown - * sequence can continue. + * Count down, since nothing will be done. The observer will be + * notified when we are done so shutdown sequence can continue. */ - try { - observer.onShutDownComplete(StorageResultCode.OperationSucceeded); - } catch (RemoteException e) { - Slog.w(TAG, "RemoteException when shutting down"); - } + mountShutdownLatch.countDown(); + Slog.i(TAG, "Unmount completed: " + path + + ", result code: " + StorageResultCode.OperationSucceeded); } } } diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 71e7bac..e83d376 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -82,6 +82,7 @@ import java.net.SocketException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.StringTokenizer; @@ -1022,6 +1023,15 @@ public class NetworkManagementService extends INetworkManagementService.Stub } } + private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) { + ArrayList<InterfaceAddress> filtered = new ArrayList<InterfaceAddress>(addresses.size()); + for (InterfaceAddress ia : addresses) { + if (!ia.getAddress().isLinkLocalAddress()) + filtered.add(ia); + } + return filtered; + } + private void modifyNat(String action, String internalInterface, String externalInterface) throws SocketException { final Command cmd = new Command("nat", action, internalInterface, externalInterface); @@ -1031,8 +1041,10 @@ public class NetworkManagementService extends INetworkManagementService.Stub if (internalNetworkInterface == null) { cmd.appendArg("0"); } else { - Collection<InterfaceAddress> interfaceAddresses = internalNetworkInterface - .getInterfaceAddresses(); + // Don't touch link-local routes, as link-local addresses aren't routable, + // kernel creates link-local routes on all interfaces automatically + List<InterfaceAddress> interfaceAddresses = excludeLinkLocal( + internalNetworkInterface.getInterfaceAddresses()); cmd.appendArg(interfaceAddresses.size()); for (InterfaceAddress ia : interfaceAddresses) { InetAddress addr = NetworkUtils.getNetworkPart( diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 699d79e..77f5182 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -37,6 +37,10 @@ import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.CellInfo; import android.telephony.TelephonyManager; +import android.telephony.DisconnectCause; +import android.telephony.PreciseCallState; +import android.telephony.PreciseDataConnectionState; +import android.telephony.PreciseDisconnectCause; import android.text.TextUtils; import android.util.Slog; @@ -125,6 +129,17 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private List<CellInfo> mCellInfo = null; + private int mRingingCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE; + + private int mForegroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE; + + private int mBackgroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE; + + private PreciseCallState mPreciseCallState = new PreciseCallState(); + + private PreciseDataConnectionState mPreciseDataConnectionState = + new PreciseDataConnectionState(); + static final int PHONE_STATE_PERMISSION_MASK = PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR | PhoneStateListener.LISTEN_CALL_STATE | @@ -132,6 +147,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { PhoneStateListener.LISTEN_DATA_CONNECTION_STATE | PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR; + static final int PRECISE_PHONE_STATE_PERMISSION_MASK = + PhoneStateListener.LISTEN_PRECISE_CALL_STATE | + PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE; + private static final int MSG_USER_SWITCHED = 1; private final Handler mHandler = new Handler() { @@ -305,6 +324,21 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { remove(r.binder); } } + if ((events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) { + try { + r.callback.onPreciseCallStateChanged(mPreciseCallState); + } catch (RemoteException ex) { + remove(r.binder); + } + } + if ((events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) { + try { + r.callback.onPreciseDataConnectionStateChanged( + mPreciseDataConnectionState); + } catch (RemoteException ex) { + remove(r.binder); + } + } } } } else { @@ -533,30 +567,47 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } handleRemoveListLocked(); } + mPreciseDataConnectionState = new PreciseDataConnectionState(state, networkType, + apnType, apn, reason, linkProperties, ""); + for (Record r : mRecords) { + if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) { + try { + r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); } broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn, apnType, linkProperties, linkCapabilities, roaming); + broadcastPreciseDataConnectionStateChanged(state, networkType, apnType, apn, reason, + linkProperties, ""); } public void notifyDataConnectionFailed(String reason, String apnType) { if (!checkNotifyPermission("notifyDataConnectionFailed()")) { return; } - /* - * This is commented out because there is no onDataConnectionFailed callback - * in PhoneStateListener. There should be. synchronized (mRecords) { - mDataConnectionFailedReason = reason; - final int N = mRecords.size(); - for (int i=N-1; i>=0; i--) { - Record r = mRecords.get(i); - if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_FAILED) != 0) { - // XXX + mPreciseDataConnectionState = new PreciseDataConnectionState( + TelephonyManager.DATA_UNKNOWN,TelephonyManager.NETWORK_TYPE_UNKNOWN, + apnType, "", reason, null, ""); + for (Record r : mRecords) { + if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) { + try { + r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } } } + handleRemoveListLocked(); } - */ broadcastDataConnectionFailed(reason, apnType); + broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN, + TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, "", reason, null, ""); } public void notifyCellLocation(Bundle cellLocation) { @@ -602,6 +653,81 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } } + public void notifyPreciseCallState(int ringingCallState, int foregroundCallState, + int backgroundCallState) { + if (!checkNotifyPermission("notifyPreciseCallState()")) { + return; + } + synchronized (mRecords) { + mRingingCallState = ringingCallState; + mForegroundCallState = foregroundCallState; + mBackgroundCallState = backgroundCallState; + mPreciseCallState = new PreciseCallState(ringingCallState, foregroundCallState, + backgroundCallState, + DisconnectCause.NOT_VALID, + PreciseDisconnectCause.NOT_VALID); + for (Record r : mRecords) { + if ((r.events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) { + try { + r.callback.onPreciseCallStateChanged(mPreciseCallState); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); + } + broadcastPreciseCallStateChanged(ringingCallState, foregroundCallState, backgroundCallState, + DisconnectCause.NOT_VALID, + PreciseDisconnectCause.NOT_VALID); + } + + public void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause) { + if (!checkNotifyPermission("notifyDisconnectCause()")) { + return; + } + synchronized (mRecords) { + mPreciseCallState = new PreciseCallState(mRingingCallState, mForegroundCallState, + mBackgroundCallState, disconnectCause, preciseDisconnectCause); + for (Record r : mRecords) { + if ((r.events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) { + try { + r.callback.onPreciseCallStateChanged(mPreciseCallState); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); + } + broadcastPreciseCallStateChanged(mRingingCallState, mForegroundCallState, + mBackgroundCallState, disconnectCause, preciseDisconnectCause); + } + + public void notifyPreciseDataConnectionFailed(String reason, String apnType, + String apn, String failCause) { + if (!checkNotifyPermission("notifyPreciseDataConnectionFailed()")) { + return; + } + synchronized (mRecords) { + mPreciseDataConnectionState = new PreciseDataConnectionState( + TelephonyManager.DATA_UNKNOWN, TelephonyManager.NETWORK_TYPE_UNKNOWN, + apnType, apn, reason, null, failCause); + for (Record r : mRecords) { + if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) { + try { + r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); + } + broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN, + TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, apn, reason, null, failCause); + } + @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) @@ -738,6 +864,33 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } + private void broadcastPreciseCallStateChanged(int ringingCallState, int foregroundCallState, + int backgroundCallState, int disconnectCause, int preciseDisconnectCause) { + Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_CALL_STATE_CHANGED); + intent.putExtra(TelephonyManager.EXTRA_RINGING_CALL_STATE, ringingCallState); + intent.putExtra(TelephonyManager.EXTRA_FOREGROUND_CALL_STATE, foregroundCallState); + intent.putExtra(TelephonyManager.EXTRA_BACKGROUND_CALL_STATE, backgroundCallState); + intent.putExtra(TelephonyManager.EXTRA_DISCONNECT_CAUSE, disconnectCause); + intent.putExtra(TelephonyManager.EXTRA_PRECISE_DISCONNECT_CAUSE, preciseDisconnectCause); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL, + android.Manifest.permission.READ_PRECISE_PHONE_STATE); + } + + private void broadcastPreciseDataConnectionStateChanged(int state, int networkType, + String apnType, String apn, String reason, LinkProperties linkProperties, String failCause) { + Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED); + intent.putExtra(PhoneConstants.STATE_KEY, state); + intent.putExtra(PhoneConstants.DATA_NETWORK_TYPE_KEY, networkType); + if (reason != null) intent.putExtra(PhoneConstants.STATE_CHANGE_REASON_KEY, reason); + if (apnType != null) intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType); + if (apn != null) intent.putExtra(PhoneConstants.DATA_APN_KEY, apn); + if (linkProperties != null) intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY, linkProperties); + if (failCause != null) intent.putExtra(PhoneConstants.DATA_FAILURE_CAUSE_KEY, failCause); + + mContext.sendBroadcastAsUser(intent, UserHandle.ALL, + android.Manifest.permission.READ_PRECISE_PHONE_STATE); + } + private boolean checkNotifyPermission(String method) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) { @@ -766,6 +919,12 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.READ_PHONE_STATE, null); } + + if ((events & PRECISE_PHONE_STATE_PERMISSION_MASK) != 0) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.READ_PRECISE_PHONE_STATE, null); + + } } private void handleRemoveListLocked() { diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 17bb3e0..d66c5a7 100644..100755 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -203,6 +203,7 @@ public final class ActiveServices { Slog.i(TAG, "Waited long enough for: " + r); mStartingBackground.remove(i); N--; + i--; } } while (mDelayedStartList.size() > 0 diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index d09ee96..8650647 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -42,6 +42,7 @@ import com.android.internal.os.BackgroundThread; import com.android.internal.os.BatteryStatsImpl; import com.android.internal.os.ProcessCpuTracker; import com.android.internal.os.TransferPipe; +import com.android.internal.os.Zygote; import com.android.internal.util.FastPrintWriter; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.MemInfoReader; @@ -61,7 +62,6 @@ import com.android.server.wm.WindowManagerService; import com.google.android.collect.Lists; import com.google.android.collect.Maps; -import dalvik.system.Zygote; import libcore.io.IoUtils; import org.xmlpull.v1.XmlPullParser; @@ -930,6 +930,11 @@ public final class ActivityManagerService extends ActivityManagerNative */ boolean mDidDexOpt; + /** + * Set if the systemServer made a call to enterSafeMode. + */ + boolean mSafeMode; + String mDebugApp = null; boolean mWaitForDebugger = false; boolean mDebugTransient = false; @@ -1058,6 +1063,7 @@ public final class ActivityManagerService extends ActivityManagerNative static final int IMMERSIVE_MODE_LOCK_MSG = 37; static final int PERSIST_URI_GRANTS_MSG = 38; static final int REQUEST_ALL_PSS_MSG = 39; + static final int UPDATE_TIME = 40; static final int FIRST_ACTIVITY_STACK_MSG = 100; static final int FIRST_BROADCAST_QUEUE_MSG = 200; @@ -1671,6 +1677,22 @@ public final class ActivityManagerService extends ActivityManagerNative requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false); break; } + case UPDATE_TIME: { + synchronized (ActivityManagerService.this) { + for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) { + ProcessRecord r = mLruProcesses.get(i); + if (r.thread != null) { + try { + r.thread.updateTimePrefs(msg.arg1 == 0 ? false : true); + } catch (RemoteException ex) { + Slog.w(TAG, "Failed to update preferences for: " + r.info.processName); + } + } + } + } + + break; + } } } }; @@ -2703,7 +2725,7 @@ public final class ActivityManagerService extends ActivityManagerNative // Run the app in safe mode if its manifest requests so or the // system is booted in safe mode. if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 || - Zygote.systemInSafeMode == true) { + mSafeMode == true) { debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE; } if ("1".equals(SystemProperties.get("debug.checkjni"))) { @@ -2716,11 +2738,16 @@ public final class ActivityManagerService extends ActivityManagerNative debugFlags |= Zygote.DEBUG_ENABLE_ASSERT; } + String requiredAbi = app.info.requiredCpuAbi; + if (requiredAbi == null) { + requiredAbi = Build.SUPPORTED_ABIS[0]; + } + // Start the process. It will either succeed and return a result containing // the PID of the new process, or else throw a RuntimeException. Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread", app.processName, uid, uid, gids, debugFlags, mountExternal, - app.info.targetSdkVersion, app.info.seinfo, null); + app.info.targetSdkVersion, app.info.seinfo, requiredAbi, null); BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics(); synchronized (bs) { @@ -8702,6 +8729,8 @@ public final class ActivityManagerService extends ActivityManagerNative } catch (RemoteException e) { } } + + mSafeMode = true; } } @@ -12305,6 +12334,7 @@ public final class ActivityManagerService extends ActivityManagerNative app.foregroundActivities = false; app.hasShownUi = false; app.hasAboveClient = false; + app.hasClientActivities = false; mServices.killServicesLocked(app, allowRestart); @@ -13317,11 +13347,20 @@ public final class ActivityManagerService extends ActivityManagerNative * of all currently running processes. This message will get queued up before the broadcast * happens. */ - if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) { + if (Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) { mHandler.sendEmptyMessage(UPDATE_TIME_ZONE); } - if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) { + /* + * If the user set the time, let all running processes know. + */ + if (Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) { + final int is24Hour = intent.getBooleanExtra( + Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1 : 0; + mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0)); + } + + if (Intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) { mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG); } diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 5a9e690..37ead27 100644..100755 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -947,8 +947,8 @@ final class ActivityRecord { // for another app to start, then we have paused dispatching // for this activity. ActivityRecord r = this; - final ActivityStack stack = task.stack; if (r.waitingVisible) { + final ActivityStack stack = mStackSupervisor.getFocusedStack(); // Hmmm, who might we be waiting for? r = stack.mResumedActivity; if (r == null) { diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index e4b196e..c6cd312 100755 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -1162,6 +1162,7 @@ final class ActivityStack { // At this point, nothing else needs to be shown if (DEBUG_VISBILITY) Slog.v(TAG, "Fullscreen: at " + r); behindFullscreen = true; + showHomeBehindStack = false; } else if (isActivityOverHome(r)) { if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r); showHomeBehindStack = true; @@ -2662,6 +2663,9 @@ final class ActivityStack { if (mResumedActivity == r) { mResumedActivity = null; } + if (mPausingActivity == r) { + mPausingActivity = null; + } if (mService.mFocusedActivity == r) { mService.mFocusedActivity = null; } diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java index 10ea67c..4c887dd 100644 --- a/services/core/java/com/android/server/am/CoreSettingsObserver.java +++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java @@ -37,11 +37,16 @@ final class CoreSettingsObserver extends ContentObserver { private static final String LOG_TAG = CoreSettingsObserver.class.getSimpleName(); // mapping form property name to its type - private static final Map<String, Class<?>> sCoreSettingToTypeMap = new HashMap< + private static final Map<String, Class<?>> sSecureSettingToTypeMap = new HashMap< + String, Class<?>>(); + private static final Map<String, Class<?>> sSystemSettingToTypeMap = new HashMap< String, Class<?>>(); static { - sCoreSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class); - // add other core settings here... + sSecureSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class); + // add other secure settings here... + + sSystemSettingToTypeMap.put(Settings.System.TIME_12_24, String.class); + // add other system settings here... } private final Bundle mCoreSettings = new Bundle(); @@ -67,39 +72,62 @@ final class CoreSettingsObserver extends ContentObserver { } private void sendCoreSettings() { - populateCoreSettings(mCoreSettings); + populateSettings(mCoreSettings, sSecureSettingToTypeMap); + populateSettings(mCoreSettings, sSystemSettingToTypeMap); mActivityManagerService.onCoreSettingsChange(mCoreSettings); } private void beginObserveCoreSettings() { - for (String setting : sCoreSettingToTypeMap.keySet()) { + for (String setting : sSecureSettingToTypeMap.keySet()) { Uri uri = Settings.Secure.getUriFor(setting); mActivityManagerService.mContext.getContentResolver().registerContentObserver( uri, false, this); } + + for (String setting : sSystemSettingToTypeMap.keySet()) { + Uri uri = Settings.System.getUriFor(setting); + mActivityManagerService.mContext.getContentResolver().registerContentObserver( + uri, false, this); + } } - private void populateCoreSettings(Bundle snapshot) { + private void populateSettings(Bundle snapshot, Map<String, Class<?>> map) { Context context = mActivityManagerService.mContext; - for (Map.Entry<String, Class<?>> entry : sCoreSettingToTypeMap.entrySet()) { + for (Map.Entry<String, Class<?>> entry : map.entrySet()) { String setting = entry.getKey(); Class<?> type = entry.getValue(); try { if (type == String.class) { - String value = Settings.Secure.getString(context.getContentResolver(), - setting); + final String value; + if (map == sSecureSettingToTypeMap) { + value = Settings.Secure.getString(context.getContentResolver(), setting); + } else { + value = Settings.System.getString(context.getContentResolver(), setting); + } snapshot.putString(setting, value); } else if (type == int.class) { - int value = Settings.Secure.getInt(context.getContentResolver(), - setting); + final int value; + if (map == sSecureSettingToTypeMap) { + value = Settings.Secure.getInt(context.getContentResolver(), setting); + } else { + value = Settings.System.getInt(context.getContentResolver(), setting); + } snapshot.putInt(setting, value); } else if (type == float.class) { - float value = Settings.Secure.getFloat(context.getContentResolver(), - setting); + final float value; + if (map == sSecureSettingToTypeMap) { + value = Settings.Secure.getFloat(context.getContentResolver(), setting); + } else { + value = Settings.System.getFloat(context.getContentResolver(), setting); + } snapshot.putFloat(setting, value); } else if (type == long.class) { - long value = Settings.Secure.getLong(context.getContentResolver(), - setting); + final long value; + if (map == sSecureSettingToTypeMap) { + value = Settings.Secure.getLong(context.getContentResolver(), setting); + } else { + value = Settings.System.getLong(context.getContentResolver(), setting); + } snapshot.putLong(setting, value); } } catch (SettingNotFoundException snfe) { diff --git a/services/core/java/com/android/server/am/NativeCrashListener.java b/services/core/java/com/android/server/am/NativeCrashListener.java index b12843b..d42d415 100644 --- a/services/core/java/com/android/server/am/NativeCrashListener.java +++ b/services/core/java/com/android/server/am/NativeCrashListener.java @@ -17,18 +17,18 @@ package com.android.server.am; import android.app.ApplicationErrorReport.CrashInfo; +import android.system.ErrnoException; +import android.system.Os; +import android.system.StructTimeval; +import android.system.StructUcred; import android.util.Slog; -import libcore.io.ErrnoException; -import libcore.io.Libcore; -import libcore.io.StructTimeval; -import libcore.io.StructUcred; - -import static libcore.io.OsConstants.*; +import static android.system.OsConstants.*; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileDescriptor; +import java.io.InterruptedIOException; import java.net.InetSocketAddress; import java.net.InetUnixAddress; @@ -76,7 +76,7 @@ final class NativeCrashListener extends Thread { try { CrashInfo ci = new CrashInfo(); ci.exceptionClassName = "Native crash"; - ci.exceptionMessage = Libcore.os.strsignal(mSignal); + ci.exceptionMessage = Os.strsignal(mSignal); ci.throwFileName = "unknown"; ci.throwClassName = "unknown"; ci.throwMethodName = "unknown"; @@ -116,22 +116,22 @@ final class NativeCrashListener extends Thread { } try { - FileDescriptor serverFd = Libcore.os.socket(AF_UNIX, SOCK_STREAM, 0); + FileDescriptor serverFd = Os.socket(AF_UNIX, SOCK_STREAM, 0); final InetUnixAddress sockAddr = new InetUnixAddress(DEBUGGERD_SOCKET_PATH); - Libcore.os.bind(serverFd, sockAddr, 0); - Libcore.os.listen(serverFd, 1); + Os.bind(serverFd, sockAddr, 0); + Os.listen(serverFd, 1); while (true) { InetSocketAddress peer = new InetSocketAddress(); FileDescriptor peerFd = null; try { if (MORE_DEBUG) Slog.v(TAG, "Waiting for debuggerd connection"); - peerFd = Libcore.os.accept(serverFd, peer); + peerFd = Os.accept(serverFd, peer); if (MORE_DEBUG) Slog.v(TAG, "Got debuggerd socket " + peerFd); if (peerFd != null) { // Only the superuser is allowed to talk to us over this socket StructUcred credentials = - Libcore.os.getsockoptUcred(peerFd, SOL_SOCKET, SO_PEERCRED); + Os.getsockoptUcred(peerFd, SOL_SOCKET, SO_PEERCRED); if (credentials.uid == 0) { // the reporting thread may take responsibility for // acking the debugger; make sure we play along. @@ -145,7 +145,7 @@ final class NativeCrashListener extends Thread { // byte written is irrelevant. if (peerFd != null) { try { - Libcore.os.write(peerFd, ackSignal, 0, 1); + Os.write(peerFd, ackSignal, 0, 1); } catch (Exception e) { /* we don't care about failures here */ if (MORE_DEBUG) { @@ -153,7 +153,7 @@ final class NativeCrashListener extends Thread { } } try { - Libcore.os.close(peerFd); + Os.close(peerFd); } catch (ErrnoException e) { if (MORE_DEBUG) { Slog.d(TAG, "Exception closing socket: " + e.getMessage()); @@ -178,10 +178,10 @@ final class NativeCrashListener extends Thread { } static int readExactly(FileDescriptor fd, byte[] buffer, int offset, int numBytes) - throws ErrnoException { + throws ErrnoException, InterruptedIOException { int totalRead = 0; while (numBytes > 0) { - int n = Libcore.os.read(fd, buffer, offset + totalRead, numBytes); + int n = Os.read(fd, buffer, offset + totalRead, numBytes); if (n <= 0) { if (DEBUG) { Slog.w(TAG, "Needed " + numBytes + " but saw " + n); @@ -202,8 +202,8 @@ final class NativeCrashListener extends Thread { try { StructTimeval timeout = StructTimeval.fromMillis(SOCKET_TIMEOUT_MILLIS); - Libcore.os.setsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO, timeout); - Libcore.os.setsockoptTimeval(fd, SOL_SOCKET, SO_SNDTIMEO, timeout); + Os.setsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO, timeout); + Os.setsockoptTimeval(fd, SOL_SOCKET, SO_SNDTIMEO, timeout); // first, the pid and signal number int headerBytes = readExactly(fd, buf, 0, 8); @@ -237,7 +237,7 @@ final class NativeCrashListener extends Thread { int bytes; do { // get some data - bytes = Libcore.os.read(fd, buf, 0, buf.length); + bytes = Os.read(fd, buf, 0, buf.length); if (bytes > 0) { if (MORE_DEBUG) { String s = new String(buf, 0, bytes, "UTF-8"); diff --git a/services/core/java/com/android/server/am/UsageStatsService.java b/services/core/java/com/android/server/am/UsageStatsService.java index 09cb344..5305c8f 100644 --- a/services/core/java/com/android/server/am/UsageStatsService.java +++ b/services/core/java/com/android/server/am/UsageStatsService.java @@ -75,42 +75,44 @@ public final class UsageStatsService extends IUsageStats.Stub { private static final boolean localLOGV = false; private static final boolean REPORT_UNEXPECTED = false; private static final String TAG = "UsageStats"; - + // Current on-disk Parcel version private static final int VERSION = 1008; private static final int CHECKIN_VERSION = 4; - + private static final String FILE_PREFIX = "usage-"; private static final String FILE_HISTORY = FILE_PREFIX + "history.xml"; - private static final int FILE_WRITE_INTERVAL = 30*60*1000; //ms - + private static final int FILE_WRITE_INTERVAL = (localLOGV) ? 0 : 30*60*1000; // 30m in ms + private static final int MAX_NUM_FILES = 5; - + private static final int NUM_LAUNCH_TIME_BINS = 10; private static final int[] LAUNCH_TIME_BINS = { 250, 500, 750, 1000, 1500, 2000, 3000, 4000, 5000 }; - + static IUsageStats sService; private Context mContext; // structure used to maintain statistics since the last checkin. - final private ArrayMap<String, PkgUsageStatsExtended> mStats; + final private ArrayMap<String, PkgUsageStatsExtended> mStats + = new ArrayMap<String, PkgUsageStatsExtended>(); // Maintains the last time any component was resumed, for all time. - final private ArrayMap<String, ArrayMap<String, Long>> mLastResumeTimes; + final private ArrayMap<String, ArrayMap<String, Long>> mLastResumeTimes + = new ArrayMap<String, ArrayMap<String, Long>>(); // To remove last-resume time stats when a pacakge is removed. private PackageMonitor mPackageMonitor; // Lock to update package stats. Methods suffixed by SLOCK should invoked with // this lock held - final Object mStatsLock; + final Object mStatsLock = new Object(); // Lock to write to file. Methods suffixed by FLOCK should invoked with // this lock held. - final Object mFileLock; + final Object mFileLock = new Object(); // Order of locks is mFileLock followed by mStatsLock to avoid deadlocks private String mLastResumedPkg; private String mLastResumedComp; @@ -120,52 +122,53 @@ public final class UsageStatsService extends IUsageStats.Stub { private String mFileLeaf; private File mDir; - private Calendar mCal; // guarded by itself + private final Calendar mCal // guarded by itself + = Calendar.getInstance(TimeZone.getTimeZone("GMT+0")); private final AtomicInteger mLastWriteDay = new AtomicInteger(-1); private final AtomicLong mLastWriteElapsedTime = new AtomicLong(0); private final AtomicBoolean mUnforcedDiskWriteRunning = new AtomicBoolean(false); - + static class TimeStats { - int count; - int[] times = new int[NUM_LAUNCH_TIME_BINS]; - + int mCount; + final int[] mTimes = new int[NUM_LAUNCH_TIME_BINS]; + TimeStats() { } - + void incCount() { - count++; + mCount++; } - + void add(int val) { final int[] bins = LAUNCH_TIME_BINS; for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) { if (val < bins[i]) { - times[i]++; + mTimes[i]++; return; } } - times[NUM_LAUNCH_TIME_BINS-1]++; + mTimes[NUM_LAUNCH_TIME_BINS-1]++; } - + TimeStats(Parcel in) { - count = in.readInt(); - final int[] localTimes = times; + mCount = in.readInt(); + final int[] localTimes = mTimes; for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) { localTimes[i] = in.readInt(); } } - + void writeToParcel(Parcel out) { - out.writeInt(count); - final int[] localTimes = times; + out.writeInt(mCount); + final int[] localTimes = mTimes; for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) { out.writeInt(localTimes[i]); } } } - - private class PkgUsageStatsExtended { + + static class PkgUsageStatsExtended { final ArrayMap<String, TimeStats> mLaunchTimes = new ArrayMap<String, TimeStats>(); final ArrayMap<String, TimeStats> mFullyDrawnTimes @@ -174,18 +177,18 @@ public final class UsageStatsService extends IUsageStats.Stub { long mUsageTime; long mPausedTime; long mResumedTime; - + PkgUsageStatsExtended() { mLaunchCount = 0; mUsageTime = 0; } - + PkgUsageStatsExtended(Parcel in) { mLaunchCount = in.readInt(); mUsageTime = in.readLong(); if (localLOGV) Slog.v(TAG, "Launch count: " + mLaunchCount + ", Usage time:" + mUsageTime); - + final int numLaunchTimeStats = in.readInt(); if (localLOGV) Slog.v(TAG, "Reading launch times: " + numLaunchTimeStats); mLaunchTimes.ensureCapacity(numLaunchTimeStats); @@ -209,16 +212,16 @@ public final class UsageStatsService extends IUsageStats.Stub { void updateResume(String comp, boolean launched) { if (launched) { - mLaunchCount ++; + mLaunchCount++; } mResumedTime = SystemClock.elapsedRealtime(); } - + void updatePause() { mPausedTime = SystemClock.elapsedRealtime(); mUsageTime += (mPausedTime - mResumedTime); } - + void addLaunchCount(String comp) { TimeStats times = mLaunchTimes.get(comp); if (times == null) { @@ -227,7 +230,7 @@ public final class UsageStatsService extends IUsageStats.Stub { } times.incCount(); } - + void addLaunchTime(String comp, int millis) { TimeStats times = mLaunchTimes.get(comp); if (times == null) { @@ -262,7 +265,7 @@ public final class UsageStatsService extends IUsageStats.Stub { mFullyDrawnTimes.valueAt(i).writeToParcel(out); } } - + void clear() { mLaunchTimes.clear(); mFullyDrawnTimes.clear(); @@ -270,32 +273,25 @@ public final class UsageStatsService extends IUsageStats.Stub { mUsageTime = 0; } } - + UsageStatsService(String dir) { - mStats = new ArrayMap<String, PkgUsageStatsExtended>(); - mLastResumeTimes = new ArrayMap<String, ArrayMap<String, Long>>(); - mStatsLock = new Object(); - mFileLock = new Object(); + if (localLOGV) Slog.v(TAG, "UsageStatsService: " + dir); mDir = new File(dir); - mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0")); - mDir.mkdir(); - - // Remove any old usage files from previous versions. + + // Remove any old /data/system/usagestats.* files from previous versions. File parentDir = mDir.getParentFile(); - String fList[] = parentDir.list(); - if (fList != null) { + String files[] = parentDir.list(); + if (files != null) { String prefix = mDir.getName() + "."; - int i = fList.length; - while (i > 0) { - i--; - if (fList[i].startsWith(prefix)) { - Slog.i(TAG, "Deleting old usage file: " + fList[i]); - (new File(parentDir, fList[i])).delete(); + for (String file : files) { + if (file.startsWith(prefix)) { + Slog.i(TAG, "Deleting old usage file: " + file); + (new File(parentDir, file)).delete(); } } } - + // Update current stats which are binned by date mFileLeaf = getCurrentDateStr(FILE_PREFIX); mFile = new File(mDir, mFileLeaf); @@ -312,11 +308,11 @@ public final class UsageStatsService extends IUsageStats.Stub { */ private String getCurrentDateStr(String prefix) { StringBuilder sb = new StringBuilder(); + if (prefix != null) { + sb.append(prefix); + } synchronized (mCal) { mCal.setTimeInMillis(System.currentTimeMillis()); - if (prefix != null) { - sb.append(prefix); - } sb.append(mCal.get(Calendar.YEAR)); int mm = mCal.get(Calendar.MONTH) - Calendar.JANUARY +1; if (mm < 10) { @@ -331,17 +327,20 @@ public final class UsageStatsService extends IUsageStats.Stub { } return sb.toString(); } - + private Parcel getParcelForFile(File file) throws IOException { FileInputStream stream = new FileInputStream(file); - byte[] raw = readFully(stream); - Parcel in = Parcel.obtain(); - in.unmarshall(raw, 0, raw.length); - in.setDataPosition(0); - stream.close(); - return in; + try { + byte[] raw = readFully(stream); + Parcel in = Parcel.obtain(); + in.unmarshall(raw, 0, raw.length); + in.setDataPosition(0); + return in; + } finally { + stream.close(); + } } - + private void readStatsFromFile() { File newFile = mFile; synchronized (mFileLock) { @@ -358,12 +357,13 @@ public final class UsageStatsService extends IUsageStats.Stub { } } } - + private void readStatsFLOCK(File file) throws IOException { Parcel in = getParcelForFile(file); int vers = in.readInt(); - if (vers != VERSION) { - Slog.w(TAG, "Usage stats version changed; dropping"); + if (vers != VERSION) { // vers will be 0 if the parcel file was empty + Slog.w(TAG, "Usage stats version of " + file + " changed from " + vers + " to " + + VERSION + "; dropping"); return; } int N = in.readInt(); @@ -384,12 +384,12 @@ public final class UsageStatsService extends IUsageStats.Stub { private void readHistoryStatsFromFile() { synchronized (mFileLock) { if (mHistoryFile.getBaseFile().exists()) { - readHistoryStatsFLOCK(mHistoryFile); + readHistoryStatsFLOCK(); } } } - private void readHistoryStatsFLOCK(AtomicFile file) { + private void readHistoryStatsFLOCK() { FileInputStream fis = null; try { fis = mHistoryFile.openRead(); @@ -472,12 +472,12 @@ public final class UsageStatsService extends IUsageStats.Stub { } return fileList; } - + private void checkFileLimitFLOCK() { // Get all usage stats output files ArrayList<String> fileList = getUsageStatsFileListFLOCK(); if (fileList == null) { - // Strange but we dont have to delete any thing + // Empty /data/system/usagestats/ so we don't have anything to delete return; } int count = fileList.size(); @@ -577,8 +577,8 @@ public final class UsageStatsService extends IUsageStats.Stub { } if (dayChanged || forceWriteHistoryStats) { - // Write history stats daily, or when forced (due to shutdown). - writeHistoryStatsFLOCK(mHistoryFile); + // Write history stats daily or when forced (due to shutdown) or when debugging. + writeHistoryStatsFLOCK(); } // Delete the backup file @@ -640,10 +640,10 @@ public final class UsageStatsService extends IUsageStats.Stub { } } - private void writeHistoryStatsFLOCK(AtomicFile historyFile) { + private void writeHistoryStatsFLOCK() { FileOutputStream fos = null; try { - fos = historyFile.startWrite(); + fos = mHistoryFile.startWrite(); XmlSerializer out = new FastXmlSerializer(); out.setOutput(fos, "utf-8"); out.startDocument(null, true); @@ -666,11 +666,11 @@ public final class UsageStatsService extends IUsageStats.Stub { out.endTag(null, "usage-history"); out.endDocument(); - historyFile.finishWrite(fos); + mHistoryFile.finishWrite(fos); } catch (IOException e) { Slog.w(TAG,"Error writing history stats" + e); if (fos != null) { - historyFile.failWrite(fos); + mHistoryFile.failWrite(fos); } } } @@ -713,7 +713,8 @@ public final class UsageStatsService extends IUsageStats.Stub { sService = asInterface(b); return sService; } - + + @Override public void noteResumeComponent(ComponentName componentName) { enforceCallingPermission(); String pkgName; @@ -722,7 +723,7 @@ public final class UsageStatsService extends IUsageStats.Stub { ((pkgName = componentName.getPackageName()) == null)) { return; } - + final boolean samePackage = pkgName.equals(mLastResumedPkg); if (mIsResumed) { if (mLastResumedPkg != null) { @@ -736,14 +737,14 @@ public final class UsageStatsService extends IUsageStats.Stub { } } } - + final boolean sameComp = samePackage && componentName.getClassName().equals(mLastResumedComp); - + mIsResumed = true; mLastResumedPkg = pkgName; mLastResumedComp = componentName.getClassName(); - + if (localLOGV) Slog.i(TAG, "started component:" + pkgName); PkgUsageStatsExtended pus = mStats.get(pkgName); if (pus == null) { @@ -764,9 +765,10 @@ public final class UsageStatsService extends IUsageStats.Stub { } } + @Override public void notePauseComponent(ComponentName componentName) { enforceCallingPermission(); - + synchronized (mStatsLock) { String pkgName; if ((componentName == null) || @@ -779,9 +781,9 @@ public final class UsageStatsService extends IUsageStats.Stub { return; } mIsResumed = false; - + if (localLOGV) Slog.i(TAG, "paused component:"+pkgName); - + PkgUsageStatsExtended pus = mStats.get(pkgName); if (pus == null) { // Weird some error here @@ -790,11 +792,12 @@ public final class UsageStatsService extends IUsageStats.Stub { } pus.updatePause(); } - + // Persist current data to file if needed. writeStatsToFile(false, false); } - + + @Override public void noteLaunchTime(ComponentName componentName, int millis) { enforceCallingPermission(); String pkgName; @@ -802,10 +805,10 @@ public final class UsageStatsService extends IUsageStats.Stub { ((pkgName = componentName.getPackageName()) == null)) { return; } - + // Persist current data to file if needed. writeStatsToFile(false, false); - + synchronized (mStatsLock) { PkgUsageStatsExtended pus = mStats.get(pkgName); if (pus != null) { @@ -813,7 +816,7 @@ public final class UsageStatsService extends IUsageStats.Stub { } } } - + public void noteFullyDrawnTime(ComponentName componentName, int millis) { enforceCallingPermission(); String pkgName; @@ -840,7 +843,8 @@ public final class UsageStatsService extends IUsageStats.Stub { mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS, Binder.getCallingPid(), Binder.getCallingUid(), null); } - + + @Override public PkgUsageStats getPkgUsageStats(ComponentName componentName) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.PACKAGE_USAGE_STATS, null); @@ -860,7 +864,8 @@ public final class UsageStatsService extends IUsageStats.Stub { return new PkgUsageStats(pkgName, launchCount, usageTime, lastResumeTimes); } } - + + @Override public PkgUsageStats[] getAllPkgUsageStats() { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.PACKAGE_USAGE_STATS, null); @@ -886,8 +891,8 @@ public final class UsageStatsService extends IUsageStats.Stub { return retArr; } } - - static byte[] readFully(FileInputStream stream) throws java.io.IOException { + + static byte[] readFully(FileInputStream stream) throws IOException { int pos = 0; int avail = stream.available(); byte[] data = new byte[avail]; @@ -905,7 +910,7 @@ public final class UsageStatsService extends IUsageStats.Stub { } } } - + private void collectDumpInfoFLOCK(PrintWriter pw, boolean isCompactOutput, boolean deleteAfterPrint, HashSet<String> packages) { List<String> fileList = getUsageStatsFileListFLOCK(); @@ -934,15 +939,12 @@ public final class UsageStatsService extends IUsageStats.Stub { // Delete old file after collecting info only for checkin requests dFile.delete(); } - } catch (FileNotFoundException e) { - Slog.w(TAG, "Failed with "+e+" when collecting dump info from file : " + file); - return; } catch (IOException e) { Slog.w(TAG, "Failed with "+e+" when collecting dump info from file : "+file); - } + } } } - + private void collectDumpInfoFromParcelFLOCK(Parcel in, PrintWriter pw, String date, boolean isCompactOutput, HashSet<String> packages) { StringBuilder sb = new StringBuilder(512); @@ -953,19 +955,19 @@ public final class UsageStatsService extends IUsageStats.Stub { } else { sb.append("Date: "); } - + sb.append(date); - + int vers = in.readInt(); if (vers != VERSION) { sb.append(" (old data version)"); pw.println(sb.toString()); return; } - + pw.println(sb.toString()); int N = in.readInt(); - + while (N > 0) { N--; String pkgName = in.readString(); @@ -992,10 +994,10 @@ public final class UsageStatsService extends IUsageStats.Stub { sb.append(activity); TimeStats times = pus.mLaunchTimes.valueAt(i); sb.append(','); - sb.append(times.count); + sb.append(times.mCount); for (int j=0; j<NUM_LAUNCH_TIME_BINS; j++) { sb.append(","); - sb.append(times.times[j]); + sb.append(times.mTimes[j]); } sb.append('\n'); } @@ -1007,7 +1009,7 @@ public final class UsageStatsService extends IUsageStats.Stub { TimeStats times = pus.mFullyDrawnTimes.valueAt(i); for (int j=0; j<NUM_LAUNCH_TIME_BINS; j++) { sb.append(","); - sb.append(times.times[j]); + sb.append(times.mTimes[j]); } sb.append('\n'); } @@ -1027,26 +1029,26 @@ public final class UsageStatsService extends IUsageStats.Stub { sb.append(pus.mLaunchTimes.keyAt(i)); TimeStats times = pus.mLaunchTimes.valueAt(i); sb.append(": "); - sb.append(times.count); + sb.append(times.mCount); sb.append(" starts"); int lastBin = 0; for (int j=0; j<NUM_LAUNCH_TIME_BINS-1; j++) { - if (times.times[j] != 0) { + if (times.mTimes[j] != 0) { sb.append(", "); sb.append(lastBin); sb.append('-'); sb.append(LAUNCH_TIME_BINS[j]); sb.append("ms="); - sb.append(times.times[j]); + sb.append(times.mTimes[j]); } lastBin = LAUNCH_TIME_BINS[j]; } - if (times.times[NUM_LAUNCH_TIME_BINS-1] != 0) { + if (times.mTimes[NUM_LAUNCH_TIME_BINS-1] != 0) { sb.append(", "); sb.append(">="); sb.append(lastBin); sb.append("ms="); - sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]); + sb.append(times.mTimes[NUM_LAUNCH_TIME_BINS-1]); } sb.append('\n'); } @@ -1059,7 +1061,7 @@ public final class UsageStatsService extends IUsageStats.Stub { boolean needComma = false; int lastBin = 0; for (int j=0; j<NUM_LAUNCH_TIME_BINS-1; j++) { - if (times.times[j] != 0) { + if (times.mTimes[j] != 0) { if (needComma) { sb.append(", "); } else { @@ -1069,27 +1071,27 @@ public final class UsageStatsService extends IUsageStats.Stub { sb.append('-'); sb.append(LAUNCH_TIME_BINS[j]); sb.append("ms="); - sb.append(times.times[j]); + sb.append(times.mTimes[j]); } lastBin = LAUNCH_TIME_BINS[j]; } - if (times.times[NUM_LAUNCH_TIME_BINS-1] != 0) { + if (times.mTimes[NUM_LAUNCH_TIME_BINS-1] != 0) { if (needComma) { sb.append(", "); } sb.append(">="); sb.append(lastBin); sb.append("ms="); - sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]); + sb.append(times.mTimes[NUM_LAUNCH_TIME_BINS-1]); } sb.append('\n'); } } - + pw.write(sb.toString()); } } - + /** * Searches array of arguments for the specified string * @param args array of argument strings @@ -1106,7 +1108,7 @@ public final class UsageStatsService extends IUsageStats.Stub { } return false; } - + /** * Searches array of arguments for the specified string's data * @param args array of argument strings @@ -1125,11 +1127,11 @@ public final class UsageStatsService extends IUsageStats.Stub { } return null; } - - @Override + /* - * The data persisted to file is parsed and the stats are computed. + * The data persisted to file is parsed and the stats are computed. */ + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingPermission(android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { @@ -1143,23 +1145,23 @@ public final class UsageStatsService extends IUsageStats.Stub { final boolean isCompactOutput = isCheckinRequest || scanArgs(args, "-c"); final boolean deleteAfterPrint = isCheckinRequest || scanArgs(args, "-d"); final String rawPackages = scanArgsData(args, "--packages"); - + // Make sure the current stats are written to the file. This // doesn't need to be done if we are deleting files after printing, - // since it that case we won't print the current stats. + // since in that case we won't print the current stats. if (!deleteAfterPrint) { writeStatsToFile(true, false); } - + HashSet<String> packages = null; if (rawPackages != null) { if (!"*".equals(rawPackages)) { // A * is a wildcard to show all packages. String[] names = rawPackages.split(","); + if (names.length != 0) { + packages = new HashSet<String>(); + } for (String n : names) { - if (packages == null) { - packages = new HashSet<String>(); - } packages.add(n); } } @@ -1169,7 +1171,7 @@ public final class UsageStatsService extends IUsageStats.Stub { Slog.w(TAG, "Checkin without packages"); return; } - + synchronized (mFileLock) { collectDumpInfoFLOCK(pw, isCompactOutput, deleteAfterPrint, packages); } diff --git a/services/core/java/com/android/server/firewall/IntentFirewall.java b/services/core/java/com/android/server/firewall/IntentFirewall.java index 88a2207..eb7a383 100644 --- a/services/core/java/com/android/server/firewall/IntentFirewall.java +++ b/services/core/java/com/android/server/firewall/IntentFirewall.java @@ -270,11 +270,13 @@ public class IntentFirewall { } File[] files = rulesDir.listFiles(); - for (int i=0; i<files.length; i++) { - File file = files[i]; + if (files != null) { + for (int i=0; i<files.length; i++) { + File file = files[i]; - if (file.getName().endsWith(".xml")) { - readRules(file, resolvers); + if (file.getName().endsWith(".xml")) { + readRules(file, resolvers); + } } } diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java index 62c0ec9..94cf668 100644 --- a/services/core/java/com/android/server/lights/LightsService.java +++ b/services/core/java/com/android/server/lights/LightsService.java @@ -78,6 +78,7 @@ public class LightsService extends SystemService { synchronized (this) { if (mColor == 0 && !mFlashing) { setLightLocked(color, LIGHT_FLASH_HARDWARE, onMS, 1000, BRIGHTNESS_MODE_USER); + mColor = 0; mH.sendMessageDelayed(Message.obtain(mH, 1, this), onMS); } } diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index 6185e50..82d3f53 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -211,29 +211,62 @@ public final class Installer extends SystemService { return execute(builder.toString()); } - public int dexopt(String apkPath, int uid, boolean isPublic) { + public int dexopt(String apkPath, int uid, boolean isPublic, String instructionSet) { StringBuilder builder = new StringBuilder("dexopt"); builder.append(' '); builder.append(apkPath); builder.append(' '); builder.append(uid); builder.append(isPublic ? " 1" : " 0"); + builder.append(" *"); // No pkgName arg present + builder.append(' '); + builder.append(instructionSet); + return execute(builder.toString()); + } + + public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName, + String instructionSet) { + StringBuilder builder = new StringBuilder("dexopt"); + builder.append(' '); + builder.append(apkPath); + builder.append(' '); + builder.append(uid); + builder.append(isPublic ? " 1" : " 0"); + builder.append(' '); + builder.append(pkgName); + builder.append(' '); + builder.append(instructionSet); return execute(builder.toString()); } - public int movedex(String srcPath, String dstPath) { + public int idmap(String targetApkPath, String overlayApkPath, int uid) { + StringBuilder builder = new StringBuilder("idmap"); + builder.append(' '); + builder.append(targetApkPath); + builder.append(' '); + builder.append(overlayApkPath); + builder.append(' '); + builder.append(uid); + return execute(builder.toString()); + } + + public int movedex(String srcPath, String dstPath, String instructionSet) { StringBuilder builder = new StringBuilder("movedex"); builder.append(' '); builder.append(srcPath); builder.append(' '); builder.append(dstPath); + builder.append(' '); + builder.append(instructionSet); return execute(builder.toString()); } - public int rmdex(String codePath) { + public int rmdex(String codePath, String instructionSet) { StringBuilder builder = new StringBuilder("rmdex"); builder.append(' '); builder.append(codePath); + builder.append(' '); + builder.append(instructionSet); return execute(builder.toString()); } @@ -320,7 +353,7 @@ public final class Installer extends SystemService { } public int getSizeInfo(String pkgName, int persona, String apkPath, String libDirPath, - String fwdLockApkPath, String asecPath, PackageStats pStats) { + String fwdLockApkPath, String asecPath, String instructionSet, PackageStats pStats) { StringBuilder builder = new StringBuilder("getsize"); builder.append(' '); builder.append(pkgName); @@ -334,6 +367,8 @@ public final class Installer extends SystemService { builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!"); builder.append(' '); builder.append(asecPath != null ? asecPath : "!"); + builder.append(' '); + builder.append(instructionSet); String s = transaction(builder.toString()); String res[] = s.split(" "); @@ -382,4 +417,15 @@ public final class Installer extends SystemService { return execute(builder.toString()); } + + public boolean restoreconData(String pkgName, String seinfo, int uid) { + StringBuilder builder = new StringBuilder("restorecondata"); + builder.append(' '); + builder.append(pkgName); + builder.append(' '); + builder.append(seinfo != null ? seinfo : "!"); + builder.append(' '); + builder.append(uid); + return (execute(builder.toString()) == 0); + } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 0f2bea6..b0428cb 100755 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -23,14 +23,15 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; +import static android.system.OsConstants.S_IRWXU; +import static android.system.OsConstants.S_IRGRP; +import static android.system.OsConstants.S_IXGRP; +import static android.system.OsConstants.S_IROTH; +import static android.system.OsConstants.S_IXOTH; import static com.android.internal.util.ArrayUtils.appendInt; import static com.android.internal.util.ArrayUtils.removeInt; -import static libcore.io.OsConstants.S_IRWXU; -import static libcore.io.OsConstants.S_IRGRP; -import static libcore.io.OsConstants.S_IXGRP; -import static libcore.io.OsConstants.S_IROTH; -import static libcore.io.OsConstants.S_IXOTH; +import android.content.pm.PackageParser.*; import com.android.internal.app.IMediaContainerService; import com.android.internal.app.ResolverActivity; import com.android.internal.content.NativeLibraryHelper; @@ -60,8 +61,8 @@ import android.content.IIntentReceiver; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentSender; -import android.content.ServiceConnection; import android.content.IntentSender.SendIntentException; +import android.content.ServiceConnection; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ContainerEncryptionParams; @@ -73,14 +74,14 @@ import android.content.pm.IPackageManager; import android.content.pm.IPackageMoveObserver; import android.content.pm.IPackageStatsObserver; import android.content.pm.InstrumentationInfo; +import android.content.pm.ManifestDigest; import android.content.pm.PackageCleanItem; import android.content.pm.PackageInfo; import android.content.pm.PackageInfoLite; import android.content.pm.PackageManager; import android.content.pm.PackageParser; -import android.content.pm.PackageUserState; -import android.content.pm.PackageParser.ActivityIntentInfo; import android.content.pm.PackageStats; +import android.content.pm.PackageUserState; import android.content.pm.ParceledListSlice; import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; @@ -88,7 +89,6 @@ import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.Signature; -import android.content.pm.ManifestDigest; import android.content.pm.VerificationParams; import android.content.pm.VerifierDeviceIdentity; import android.content.pm.VerifierInfo; @@ -99,6 +99,7 @@ import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Environment; +import android.os.Environment.UserEnvironment; import android.os.FileObserver; import android.os.FileUtils; import android.os.Handler; @@ -115,10 +116,12 @@ import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; -import android.os.Environment.UserEnvironment; import android.os.UserManager; import android.security.KeyStore; import android.security.SystemKeyStore; +import android.system.ErrnoException; +import android.system.Os; +import android.system.StructStat; import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.EventLog; @@ -157,10 +160,8 @@ import java.util.List; import java.util.Map; import java.util.Set; -import libcore.io.ErrnoException; +import dalvik.system.VMRuntime; import libcore.io.IoUtils; -import libcore.io.Libcore; -import libcore.io.StructStat; import com.android.internal.R; import com.android.server.storage.DeviceStorageMonitorInternal; @@ -219,7 +220,8 @@ public class PackageManagerService extends IPackageManager.Stub { static final int SCAN_UPDATE_TIME = 1<<6; static final int SCAN_DEFER_DEX = 1<<7; static final int SCAN_BOOTING = 1<<8; - static final int SCAN_DELETE_DATA_ON_FAILURES = 1<<9; + static final int SCAN_TRUSTED_OVERLAY = 1<<9; + static final int SCAN_DELETE_DATA_ON_FAILURES = 1<<10; static final int REMOVE_CHATTY = 1<<16; @@ -259,10 +261,19 @@ public class PackageManagerService extends IPackageManager.Stub { private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive"; private static final String LIB_DIR_NAME = "lib"; + private static final String LIB64_DIR_NAME = "lib64"; + + private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay"; static final String mTempContainerPrefix = "smdl2tmp"; final ServiceThread mHandlerThread; + + private static String sPreferredInstructionSet; + + private static final String IDMAP_PREFIX = "/data/resource-cache/"; + private static final String IDMAP_SUFFIX = "@idmap"; + final PackageHandler mHandler; final int mSdkVersion = Build.VERSION.SDK_INT; @@ -298,6 +309,9 @@ public class PackageManagerService extends IPackageManager.Stub { // This is the object monitoring the system app dir. final FileObserver mVendorInstallObserver; + // This is the object monitoring the vendor overlay package dir. + final FileObserver mVendorOverlayInstallObserver; + // This is the object monitoring mAppInstallDir. final FileObserver mAppInstallObserver; @@ -344,6 +358,10 @@ public class PackageManagerService extends IPackageManager.Stub { final HashMap<String, PackageParser.Package> mPackages = new HashMap<String, PackageParser.Package>(); + // Tracks available target package names -> overlay package paths. + final HashMap<String, HashMap<String, PackageParser.Package>> mOverlays = + new HashMap<String, HashMap<String, PackageParser.Package>>(); + final Settings mSettings; boolean mRestoredSettings; @@ -381,6 +399,9 @@ public class PackageManagerService extends IPackageManager.Stub { // If mac_permissions.xml was found for seinfo labeling. boolean mFoundPolicyFile; + // If a recursive restorecon of /data/data/<pkg> is needed. + private boolean mShouldRestoreconData = SELinuxMMAC.shouldRestorecon(); + // All available activities, for your resolving pleasure. final ActivityIntentResolver mActivities = new ActivityIntentResolver(); @@ -1191,27 +1212,38 @@ public class PackageManagerService extends IPackageManager.Stub { boolean didDexOpt = false; + final List<String> instructionSets = getAllInstructionSets(); + /** * Ensure all external libraries have had dexopt run on them. */ if (mSharedLibraries.size() > 0) { - Iterator<SharedLibraryEntry> libs = mSharedLibraries.values().iterator(); - while (libs.hasNext()) { - String lib = libs.next().path; - if (lib == null) { - continue; - } - try { - if (dalvik.system.DexFile.isDexOptNeeded(lib)) { - alreadyDexOpted.add(lib); - mInstaller.dexopt(lib, Process.SYSTEM_UID, true); - didDexOpt = true; + // NOTE: For now, we're compiling these system "shared libraries" + // (and framework jars) into all available architectures. It's possible + // to compile them only when we come across an app that uses them (there's + // already logic for that in scanPackageLI) but that adds some complexity. + for (String instructionSet : instructionSets) { + for (SharedLibraryEntry libEntry : mSharedLibraries.values()) { + final String lib = libEntry.path; + if (lib == null) { + continue; + } + + try { + if (dalvik.system.DexFile.isDexOptNeededInternal( + lib, null, instructionSet, false)) { + alreadyDexOpted.add(lib); + + // The list of "shared libraries" we have at this point is + mInstaller.dexopt(lib, Process.SYSTEM_UID, true, instructionSet); + didDexOpt = true; + } + } catch (FileNotFoundException e) { + Slog.w(TAG, "Library not found: " + lib); + } catch (IOException e) { + Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? " + + e.getMessage()); } - } catch (FileNotFoundException e) { - Slog.w(TAG, "Library not found: " + lib); - } catch (IOException e) { - Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? " - + e.getMessage()); } } } @@ -1234,51 +1266,50 @@ public class PackageManagerService extends IPackageManager.Stub { */ String[] frameworkFiles = frameworkDir.list(); if (frameworkFiles != null) { - for (int i=0; i<frameworkFiles.length; i++) { - File libPath = new File(frameworkDir, frameworkFiles[i]); - String path = libPath.getPath(); - // Skip the file if we alrady did it. - if (alreadyDexOpted.contains(path)) { - continue; - } - // Skip the file if it is not a type we want to dexopt. - if (!path.endsWith(".apk") && !path.endsWith(".jar")) { - continue; - } - try { - if (dalvik.system.DexFile.isDexOptNeeded(path)) { - mInstaller.dexopt(path, Process.SYSTEM_UID, true); - didDexOpt = true; + // TODO: We could compile these only for the most preferred ABI. We should + // first double check that the dex files for these commands are not referenced + // by other system apps. + for (String instructionSet : instructionSets) { + for (int i=0; i<frameworkFiles.length; i++) { + File libPath = new File(frameworkDir, frameworkFiles[i]); + String path = libPath.getPath(); + // Skip the file if we already did it. + if (alreadyDexOpted.contains(path)) { + continue; + } + // Skip the file if it is not a type we want to dexopt. + if (!path.endsWith(".apk") && !path.endsWith(".jar")) { + continue; + } + try { + if (dalvik.system.DexFile.isDexOptNeededInternal(path, null, instructionSet, false)) { + mInstaller.dexopt(path, Process.SYSTEM_UID, true, instructionSet); + didDexOpt = true; + } + } catch (FileNotFoundException e) { + Slog.w(TAG, "Jar not found: " + path); + } catch (IOException e) { + Slog.w(TAG, "Exception reading jar: " + path, e); } - } catch (FileNotFoundException e) { - Slog.w(TAG, "Jar not found: " + path); - } catch (IOException e) { - Slog.w(TAG, "Exception reading jar: " + path, e); } } } if (didDexOpt) { - File dalvikCacheDir = new File(dataDir, "dalvik-cache"); - - // If we had to do a dexopt of one of the previous - // things, then something on the system has changed. - // Consider this significant, and wipe away all other - // existing dexopt files to ensure we don't leave any - // dangling around. - String[] files = dalvikCacheDir.list(); - if (files != null) { - for (int i=0; i<files.length; i++) { - String fn = files[i]; - if (fn.startsWith("data@app@") - || fn.startsWith("data@app-private@")) { - Slog.i(TAG, "Pruning dalvik file: " + fn); - (new File(dalvikCacheDir, fn)).delete(); - } - } - } + pruneDexFiles(new File(dataDir, "dalvik-cache")); } + // Collect vendor overlay packages. + // (Do this before scanning any apps.) + // For security and version matching reason, only consider + // overlay packages if they reside in VENDOR_OVERLAY_DIR. + File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR); + mVendorOverlayInstallObserver = new AppDirObserver( + vendorOverlayDir.getPath(), OBSERVER_EVENTS, true, false); + mVendorOverlayInstallObserver.startWatching(); + scanDirLI(vendorOverlayDir, PackageParser.PARSE_IS_SYSTEM + | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode | SCAN_TRUSTED_OVERLAY, 0); + // Find base frameworks (resource packages without code). mFrameworkInstallObserver = new AppDirObserver( frameworkDir.getPath(), OBSERVER_EVENTS, true, false); @@ -1307,6 +1338,11 @@ public class PackageManagerService extends IPackageManager.Stub { // Collect all vendor packages. File vendorAppDir = new File("/vendor/app"); + try { + vendorAppDir = vendorAppDir.getCanonicalFile(); + } catch (IOException e) { + // failed to look up canonical path, continue with original one + } mVendorInstallObserver = new AppDirObserver( vendorAppDir.getPath(), OBSERVER_EVENTS, true, false); mVendorInstallObserver.startWatching(); @@ -1430,6 +1466,12 @@ public class PackageManagerService extends IPackageManager.Stub { // the correct library paths. updateAllSharedLibrariesLPw(); + + for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) { + adjustCpuAbisForSharedUserLPw(setting.packages, true /* do dexopt */, + false /* force dexopt */, false /* defer dexopt */); + } + EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END, SystemClock.uptimeMillis()); Slog.i(TAG, "Time to scan packages: " @@ -1476,6 +1518,37 @@ public class PackageManagerService extends IPackageManager.Stub { } // synchronized (mInstallLock) } + private static void pruneDexFiles(File cacheDir) { + // If we had to do a dexopt of one of the previous + // things, then something on the system has changed. + // Consider this significant, and wipe away all other + // existing dexopt files to ensure we don't leave any + // dangling around. + // + // Additionally, delete all dex files from the root directory + // since there shouldn't be any there anyway. + File[] files = cacheDir.listFiles(); + if (files != null) { + for (File file : files) { + if (!file.isDirectory()) { + Slog.i(TAG, "Pruning dalvik file: " + file.getAbsolutePath()); + file.delete(); + } else { + File[] subDirList = file.listFiles(); + if (subDirList != null) { + for (File subDirFile : subDirList) { + final String fn = subDirFile.getName(); + if (fn.startsWith("data@app@") || fn.startsWith("data@app-private@")) { + Slog.i(TAG, "Pruning dalvik file: " + fn); + subDirFile.delete(); + } + } + } + } + } + } + } + public boolean isFirstBoot() { return !mRestoredSettings; } @@ -1766,7 +1839,6 @@ public class PackageManagerService extends IPackageManager.Stub { PackageInfo generatePackageInfo(PackageParser.Package p, int flags, int userId) { if (!sUserManager.exists(userId)) return null; - PackageInfo pi; final PackageSetting ps = (PackageSetting) p.mExtras; if (ps == null) { return null; @@ -1979,6 +2051,7 @@ public class PackageManagerService extends IPackageManager.Stub { pkg.applicationInfo.dataDir = getDataPathForPackage(packageName, 0).getPath(); pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString; + pkg.applicationInfo.requiredCpuAbi = ps.requiredCpuAbiString; } return generatePackageInfo(pkg, flags, userId); } @@ -3502,6 +3575,56 @@ public class PackageManagerService extends IPackageManager.Stub { return finalList; } + private void createIdmapsForPackageLI(PackageParser.Package pkg) { + HashMap<String, PackageParser.Package> overlays = mOverlays.get(pkg.packageName); + if (overlays == null) { + Slog.w(TAG, "Unable to create idmap for " + pkg.packageName + ": no overlay packages"); + return; + } + for (PackageParser.Package opkg : overlays.values()) { + // Not much to do if idmap fails: we already logged the error + // and we certainly don't want to abort installation of pkg simply + // because an overlay didn't fit properly. For these reasons, + // ignore the return value of createIdmapForPackagePairLI. + createIdmapForPackagePairLI(pkg, opkg); + } + } + + private boolean createIdmapForPackagePairLI(PackageParser.Package pkg, + PackageParser.Package opkg) { + if (!opkg.mTrustedOverlay) { + Slog.w(TAG, "Skipping target and overlay pair " + pkg.mScanPath + " and " + + opkg.mScanPath + ": overlay not trusted"); + return false; + } + HashMap<String, PackageParser.Package> overlaySet = mOverlays.get(pkg.packageName); + if (overlaySet == null) { + Slog.e(TAG, "was about to create idmap for " + pkg.mScanPath + " and " + + opkg.mScanPath + " but target package has no known overlays"); + return false; + } + final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); + if (mInstaller.idmap(pkg.mScanPath, opkg.mScanPath, sharedGid) != 0) { + Slog.e(TAG, "Failed to generate idmap for " + pkg.mScanPath + " and " + opkg.mScanPath); + return false; + } + PackageParser.Package[] overlayArray = + overlaySet.values().toArray(new PackageParser.Package[0]); + Comparator<PackageParser.Package> cmp = new Comparator<PackageParser.Package>() { + public int compare(PackageParser.Package p1, PackageParser.Package p2) { + return p1.mOverlayPriority - p2.mOverlayPriority; + } + }; + Arrays.sort(overlayArray, cmp); + + pkg.applicationInfo.resourceDirs = new String[overlayArray.length]; + int i = 0; + for (PackageParser.Package p : overlayArray) { + pkg.applicationInfo.resourceDirs[i++] = p.applicationInfo.sourceDir; + } + return true; + } + private void scanDirLI(File dir, int flags, int scanMode, long currentTime) { String[] files = dir.list(); if (files == null) { @@ -3599,7 +3722,7 @@ public class PackageManagerService extends IPackageManager.Stub { pp.setSeparateProcesses(mSeparateProcesses); pp.setOnlyCoreApps(mOnlyCore); final PackageParser.Package pkg = pp.parsePackage(scanFile, - scanPath, mMetrics, parseFlags); + scanPath, mMetrics, parseFlags, (scanMode & SCAN_TRUSTED_OVERLAY) != 0); if (pkg == null) { mLastScanError = pp.getParseError(); @@ -3627,6 +3750,7 @@ public class PackageManagerService extends IPackageManager.Stub { updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName); if (DEBUG_INSTALL && updatedPkg != null) Slog.d(TAG, "updatedPkg = " + updatedPkg); } + boolean updatedPkgBetter = false; // First check if this is a system package that may involve an update if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) { if (ps != null && !ps.codePath.equals(scanFile)) { @@ -3674,13 +3798,15 @@ public class PackageManagerService extends IPackageManager.Stub { + " better than installed " + ps.versionCode); InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps), - ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString); + ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString, + getAppInstructionSetFromSettings(ps)); synchronized (mInstallLock) { args.cleanUpResourcesLI(); } synchronized (mPackages) { mSettings.enableSystemPackageLPw(ps.name); } + updatedPkgBetter = true; } } } @@ -3737,7 +3863,8 @@ public class PackageManagerService extends IPackageManager.Stub { + ps.codePathString + ": new version " + pkg.mVersionCode + " better than installed " + ps.versionCode); InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps), - ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString); + ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString, + getAppInstructionSetFromSettings(ps)); synchronized (mInstallLock) { args.cleanUpResourcesLI(); } @@ -3757,7 +3884,7 @@ public class PackageManagerService extends IPackageManager.Stub { String codePath = null; String resPath = null; - if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) { + if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) { if (ps != null && ps.resourcePathString != null) { resPath = ps.resourcePathString; } else { @@ -3850,12 +3977,16 @@ public class PackageManagerService extends IPackageManager.Stub { } } + @Override public void performBootDexOpt() { - HashSet<PackageParser.Package> pkgs = null; + enforceSystemOrRoot("Only the system can request dexopt be performed"); + + final HashSet<PackageParser.Package> pkgs; synchronized (mPackages) { pkgs = mDeferredDexOpt; mDeferredDexOpt = null; } + if (pkgs != null) { int i = 0; for (PackageParser.Package pkg : pkgs) { @@ -3872,16 +4003,17 @@ public class PackageManagerService extends IPackageManager.Stub { PackageParser.Package p = pkg; synchronized (mInstallLock) { if (!p.mDidDexOpt) { - performDexOptLI(p, false, false, true); + performDexOptLI(p, false /* force dex */, false /* defer */, + true /* include dependencies */); } } } } } + @Override public boolean performDexOpt(String packageName) { enforceSystemOrRoot("Only the system can request dexopt be performed"); - if (!mNoDexOpt) { return false; } @@ -3894,12 +4026,13 @@ public class PackageManagerService extends IPackageManager.Stub { } } synchronized (mInstallLock) { - return performDexOptLI(p, false, false, true) == DEX_OPT_PERFORMED; + return performDexOptLI(p, false /* force dex */, false /* defer */, + true /* include dependencies */) == DEX_OPT_PERFORMED; } } - private void performDexOptLibsLI(ArrayList<String> libs, boolean forceDex, boolean defer, - HashSet<String> done) { + private void performDexOptLibsLI(ArrayList<String> libs, String instructionSet, boolean forceDex, + boolean defer, HashSet<String> done) { for (int i=0; i<libs.size(); i++) { PackageParser.Package libPkg; String libName; @@ -3913,7 +4046,7 @@ public class PackageManagerService extends IPackageManager.Stub { } } if (libPkg != null && !done.contains(libName)) { - performDexOptLI(libPkg, forceDex, defer, done); + performDexOptLI(libPkg, instructionSet, forceDex, defer, done); } } } @@ -3923,23 +4056,29 @@ 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, - HashSet<String> done) { - boolean performed = false; + private int performDexOptLI(PackageParser.Package pkg, String instructionSetOverride, + boolean forceDex, + boolean defer, HashSet<String> done) { + final String instructionSet = instructionSetOverride != null ? + instructionSetOverride : getAppInstructionSet(pkg.applicationInfo); + if (done != null) { done.add(pkg.packageName); if (pkg.usesLibraries != null) { - performDexOptLibsLI(pkg.usesLibraries, forceDex, defer, done); + performDexOptLibsLI(pkg.usesLibraries, instructionSet, forceDex, defer, done); } if (pkg.usesOptionalLibraries != null) { - performDexOptLibsLI(pkg.usesOptionalLibraries, forceDex, defer, done); + performDexOptLibsLI(pkg.usesOptionalLibraries, instructionSet, forceDex, defer, done); } } + + boolean performed = false; 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 || dalvik.system.DexFile.isDexOptNeededInternal(path, + pkg.packageName, instructionSet, defer)) { if (!forceDex && defer) { if (mDeferredDexOpt == null) { mDeferredDexOpt = new HashSet<PackageParser.Package>(); @@ -3947,9 +4086,12 @@ public class PackageManagerService extends IPackageManager.Stub { mDeferredDexOpt.add(pkg); return DEX_OPT_DEFERRED; } else { - Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName); + Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName + + " (instructionSet=" + instructionSet + ")"); + final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); - ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg)); + ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg), + pkg.packageName, instructionSet); pkg.mDidDexOpt = true; performed = true; } @@ -3976,17 +4118,58 @@ public class PackageManagerService extends IPackageManager.Stub { return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED; } + private String getAppInstructionSet(ApplicationInfo info) { + String instructionSet = getPreferredInstructionSet(); + + if (info.requiredCpuAbi != null) { + instructionSet = VMRuntime.getInstructionSet(info.requiredCpuAbi); + } + + return instructionSet; + } + + private String getAppInstructionSetFromSettings(PackageSetting ps) { + String instructionSet = getPreferredInstructionSet(); + + if (ps.requiredCpuAbiString != null) { + instructionSet = VMRuntime.getInstructionSet(ps.requiredCpuAbiString); + } + + return instructionSet; + } + + private static String getPreferredInstructionSet() { + if (sPreferredInstructionSet == null) { + sPreferredInstructionSet = VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]); + } + + return sPreferredInstructionSet; + } + + private static List<String> getAllInstructionSets() { + final String[] allAbis = Build.SUPPORTED_ABIS; + final List<String> allInstructionSets = new ArrayList<String>(allAbis.length); + + for (String abi : allAbis) { + final String instructionSet = VMRuntime.getInstructionSet(abi); + if (!allInstructionSets.contains(instructionSet)) { + allInstructionSets.add(instructionSet); + } + } + + return allInstructionSets; + } + 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); + return performDexOptLI(pkg, null /* instruction set override */, forceDex, defer, done); } private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) { @@ -4090,6 +4273,14 @@ public class PackageManagerService extends IPackageManager.Stub { private boolean updateSharedLibrariesLPw(PackageParser.Package pkg, PackageParser.Package changingLib) { + // We might be upgrading from a version of the platform that did not + // provide per-package native library directories for system apps. + // Fix that up here. + if (isSystemApp(pkg)) { + PackageSetting ps = mSettings.mPackages.get(pkg.applicationInfo.packageName); + setInternalAppNativeLibraryPath(pkg, ps); + } + if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) { if (mTmpSharedLibraries == null || mTmpSharedLibraries.length < mSharedLibraries.size()) { @@ -4255,17 +4446,6 @@ public class PackageManagerService extends IPackageManager.Stub { // writer synchronized (mPackages) { - 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; - } - } - if (pkg.mSharedUserId != null) { suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, true); if (suid == null) { @@ -4340,6 +4520,7 @@ public class PackageManagerService extends IPackageManager.Stub { // the PkgSetting exists already and doesn't have to be created. pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile, destResourceFile, pkg.applicationInfo.nativeLibraryDir, + pkg.applicationInfo.requiredCpuAbi, pkg.applicationInfo.flags, user, false); if (pkgSetting == null) { Slog.w(TAG, "Creating application package " + pkg.packageName + " failed"); @@ -4375,6 +4556,17 @@ public class PackageManagerService extends IPackageManager.Stub { pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; } + 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; + } + } + if (mFoundPolicyFile) { SELinuxMMAC.assignSeinfoValue(pkg); } @@ -4475,7 +4667,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (dataPath.exists()) { int currentUid = 0; try { - StructStat stat = Libcore.os.stat(dataPath.getPath()); + StructStat stat = Os.stat(dataPath.getPath()); currentUid = stat.st_uid; } catch (ErrnoException e) { Slog.e(TAG, "Couldn't stat path " + dataPath.getPath(), e); @@ -4558,6 +4750,11 @@ public class PackageManagerService extends IPackageManager.Stub { } } pkg.applicationInfo.dataDir = dataPath.getPath(); + if (mShouldRestoreconData) { + Slog.i(TAG, "SELinux relabeling of " + pkg.packageName + " issued."); + mInstaller.restoreconData(pkg.packageName, pkg.applicationInfo.seinfo, + pkg.applicationInfo.uid); + } } else { if (DEBUG_PACKAGE_SCANNING) { if ((parseFlags & PackageParser.PARSE_CHATTY) != 0) @@ -4596,7 +4793,6 @@ public class PackageManagerService extends IPackageManager.Stub { pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString; } } - pkgSetting.uidError = uidError; } @@ -4628,6 +4824,8 @@ public class PackageManagerService extends IPackageManager.Stub { Log.i(TAG, "removed obsolete native libraries for system package " + path); } + + setInternalAppAbi(pkg, pkgSetting); } else { if (!isForwardLocked(pkg) && !isExternal(pkg)) { /* @@ -4640,16 +4838,47 @@ public class PackageManagerService extends IPackageManager.Stub { } try { - if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) { + int copyRet = copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir); + if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) { Slog.e(TAG, "Unable to copy native libraries"); mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; return null; } + + // We've successfully copied native libraries across, so we make a + // note of what ABI we're using + if (copyRet != PackageManager.NO_NATIVE_LIBRARIES) { + pkg.applicationInfo.requiredCpuAbi = Build.SUPPORTED_ABIS[copyRet]; + } else { + pkg.applicationInfo.requiredCpuAbi = null; + } } catch (IOException e) { Slog.e(TAG, "Unable to copy native libraries", e); mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; return null; } + } else { + // We don't have to copy the shared libraries if we're in the ASEC container + // but we still need to scan the file to figure out what ABI the app needs. + // + // TODO: This duplicates work done in the default container service. It's possible + // to clean this up but we'll need to change the interface between this service + // and IMediaContainerService (but doing so will spread this logic out, rather + // than centralizing it). + final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(scanFile); + final int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS); + if (abi >= 0) { + pkg.applicationInfo.requiredCpuAbi = Build.SUPPORTED_ABIS[abi]; + } else if (abi == PackageManager.NO_NATIVE_LIBRARIES) { + // Note that (non upgraded) system apps will not have any native + // libraries bundled in their APK, but we're guaranteed not to be + // such an app at this point. + pkg.applicationInfo.requiredCpuAbi = null; + } else { + mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; + return null; + } + handle.close(); } if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path); @@ -4726,8 +4955,7 @@ public class PackageManagerService extends IPackageManager.Stub { } if (allowed) { if (!mSharedLibraries.containsKey(name)) { - mSharedLibraries.put(name, new SharedLibraryEntry(null, - pkg.packageName)); + 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"); @@ -4800,6 +5028,12 @@ public class PackageManagerService extends IPackageManager.Stub { // writer synchronized (mPackages) { + if ((scanMode&SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) { + // We don't do this here during boot because we can do it all + // at once after scanning all existing packages. + adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages, + true, forceDex, (scanMode & SCAN_DEFER_DEX) != 0); + } // We don't expect installation to fail beyond this point, if ((scanMode&SCAN_MONITOR) != 0) { mAppDirs.put(pkg.mPath, pkg); @@ -5115,11 +5349,83 @@ public class PackageManagerService extends IPackageManager.Stub { } pkgSetting.setTimeStamp(scanFileTime); + + // Create idmap files for pairs of (packages, overlay packages). + // Note: "android", ie framework-res.apk, is handled by native layers. + if (pkg.mOverlayTarget != null) { + // This is an overlay package. + if (pkg.mOverlayTarget != null && !pkg.mOverlayTarget.equals("android")) { + if (!mOverlays.containsKey(pkg.mOverlayTarget)) { + mOverlays.put(pkg.mOverlayTarget, + new HashMap<String, PackageParser.Package>()); + } + HashMap<String, PackageParser.Package> map = mOverlays.get(pkg.mOverlayTarget); + map.put(pkg.packageName, pkg); + PackageParser.Package orig = mPackages.get(pkg.mOverlayTarget); + if (orig != null && !createIdmapForPackagePairLI(orig, pkg)) { + mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE; + return null; + } + } + } else if (mOverlays.containsKey(pkg.packageName) && + !pkg.packageName.equals("android")) { + // This is a regular package, with one or more known overlay packages. + createIdmapsForPackageLI(pkg); + } } return pkg; } + public void adjustCpuAbisForSharedUserLPw(Set<PackageSetting> packagesForUser, + boolean doDexOpt, boolean forceDexOpt, boolean deferDexOpt) { + String requiredInstructionSet = null; + PackageSetting requirer = null; + for (PackageSetting ps : packagesForUser) { + if (ps.requiredCpuAbiString != null) { + final String instructionSet = VMRuntime.getInstructionSet(ps.requiredCpuAbiString); + if (requiredInstructionSet != null) { + if (!instructionSet.equals(requiredInstructionSet)) { + // We have a mismatch between instruction sets (say arm vs arm64). + // + // TODO: We should rescan all the packages in a shared UID to check if + // they do contain shared libs for other ABIs in addition to the ones we've + // already extracted. For example, the package might contain both arm64-v8a + // and armeabi-v7a shared libs, and we'd have chosen arm64-v8a on 64 bit + // devices. + String errorMessage = "Instruction set mismatch, " + requirer.pkg.packageName + + " requires " + requiredInstructionSet + " whereas " + ps.pkg.packageName + + " requires " + instructionSet; + Slog.e(TAG, errorMessage); + + reportSettingsProblem(Log.WARN, errorMessage); + // Give up, don't bother making any other changes to the package settings. + return; + } + } else { + requiredInstructionSet = instructionSet; + requirer = ps; + } + } + } + + if (requiredInstructionSet != null) { + for (PackageSetting ps : packagesForUser) { + if (ps.requiredCpuAbiString == null) { + ps.requiredCpuAbiString = requirer.requiredCpuAbiString; + if (ps.pkg != null) { + ps.pkg.applicationInfo.requiredCpuAbi = requirer.requiredCpuAbiString; + Slog.i(TAG, "Adjusting ABI for : " + ps.name + " to " + ps.requiredCpuAbiString); + if (doDexOpt) { + performDexOptLI(ps.pkg, forceDexOpt, deferDexOpt, true); + mInstaller.rmdex(ps.codePathString, getPreferredInstructionSet()); + } + } + } + } + } + } + private void setUpCustomResolverActivity(PackageParser.Package pkg) { synchronized (mPackages) { mResolverReplaced = true; @@ -5144,14 +5450,86 @@ public class PackageManagerService extends IPackageManager.Stub { } } + private String calculateApkRoot(final String codePathString) { + final File codePath = new File(codePathString); + final File codeRoot; + if (FileUtils.contains(Environment.getRootDirectory(), codePath)) { + codeRoot = Environment.getRootDirectory(); + } else if (FileUtils.contains(Environment.getOemDirectory(), codePath)) { + codeRoot = Environment.getOemDirectory(); + } else if (FileUtils.contains(Environment.getVendorDirectory(), codePath)) { + codeRoot = Environment.getVendorDirectory(); + } else { + // Unrecognized code path; take its top real segment as the apk root: + // e.g. /something/app/blah.apk => /something + try { + File f = codePath.getCanonicalFile(); + File parent = f.getParentFile(); // non-null because codePath is a file + File tmp; + while ((tmp = parent.getParentFile()) != null) { + f = parent; + parent = tmp; + } + codeRoot = f; + Slog.w(TAG, "Unrecognized code path " + + codePath + " - using " + codeRoot); + } catch (IOException e) { + // Can't canonicalize the lib path -- shenanigans? + Slog.w(TAG, "Can't canonicalize code path " + codePath); + return Environment.getRootDirectory().getPath(); + } + } + return codeRoot.getPath(); + } + + // This is the initial scan-time determination of how to handle a given + // package for purposes of native library location. private void setInternalAppNativeLibraryPath(PackageParser.Package pkg, PackageSetting pkgSetting) { - final String apkLibPath = getApkName(pkgSetting.codePathString); - final String nativeLibraryPath = new File(mAppLibInstallDir, apkLibPath).getPath(); + // "bundled" here means system-installed with no overriding update + final boolean bundledApk = isSystemApp(pkg) && !isUpdatedSystemApp(pkg); + final String apkName = getApkName(pkg.applicationInfo.sourceDir); + final File libDir; + if (bundledApk) { + // If "/system/lib64/apkname" exists, assume that is the per-package + // native library directory to use; otherwise use "/system/lib/apkname". + String apkRoot = calculateApkRoot(pkg.applicationInfo.sourceDir); + File lib64 = new File(apkRoot, LIB64_DIR_NAME); + File packLib64 = new File(lib64, apkName); + libDir = (packLib64.exists()) ? lib64 : new File(apkRoot, LIB_DIR_NAME); + } else { + libDir = mAppLibInstallDir; + } + final String nativeLibraryPath = (new File(libDir, apkName)).getPath(); pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath; pkgSetting.nativeLibraryPathString = nativeLibraryPath; } + // Deduces the required ABI of an upgraded system app. + private void setInternalAppAbi(PackageParser.Package pkg, PackageSetting pkgSetting) { + final String apkRoot = calculateApkRoot(pkg.applicationInfo.sourceDir); + final String apkName = getApkName(pkg.applicationInfo.sourceDir); + + // This is of the form "/system/lib64/<packagename>", "/vendor/lib64/<packagename>" + // or similar. + final File lib64 = new File(apkRoot, new File(LIB64_DIR_NAME, apkName).getPath()); + final File lib = new File(apkRoot, new File(LIB_DIR_NAME, apkName).getPath()); + + // Assume that the bundled native libraries always correspond to the + // most preferred 32 or 64 bit ABI. + if (lib64.exists()) { + pkg.applicationInfo.requiredCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0]; + pkgSetting.requiredCpuAbiString = Build.SUPPORTED_64_BIT_ABIS[0]; + } else if (lib.exists()) { + pkg.applicationInfo.requiredCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0]; + pkgSetting.requiredCpuAbiString = Build.SUPPORTED_32_BIT_ABIS[0]; + } else { + // This is the case where the app has no native code. + pkg.applicationInfo.requiredCpuAbi = null; + pkgSetting.requiredCpuAbiString = null; + } + } + private static int copyNativeLibrariesForInternalApp(File scanFile, final File nativeLibraryDir) throws IOException { if (!nativeLibraryDir.isDirectory()) { @@ -5162,8 +5540,7 @@ public class PackageManagerService extends IPackageManager.Stub { } try { - Libcore.os.chmod(nativeLibraryDir.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH - | S_IXOTH); + Os.chmod(nativeLibraryDir.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); } catch (ErrnoException e) { throw new IOException("Cannot chmod native library directory " + nativeLibraryDir.getPath(), e); @@ -5176,7 +5553,21 @@ public class PackageManagerService extends IPackageManager.Stub { * If this is an internal application or our nativeLibraryPath points to * the app-lib directory, unpack the libraries if necessary. */ - return NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir); + final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(scanFile); + try { + int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS); + if (abi >= 0) { + int copyRet = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, + nativeLibraryDir, Build.SUPPORTED_ABIS[abi]); + if (copyRet != PackageManager.INSTALL_SUCCEEDED) { + return copyRet; + } + } + + return abi; + } finally { + handle.close(); + } } private void killApplication(String pkgName, int appId, String reason) { @@ -7719,7 +8110,8 @@ public class PackageManagerService extends IPackageManager.Stub { int mRet; MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags, - String packageName, String dataDir, int uid, UserHandle user) { + String packageName, String dataDir, String instructionSet, + int uid, UserHandle user) { super(user); this.srcArgs = srcArgs; this.observer = observer; @@ -7728,7 +8120,7 @@ public class PackageManagerService extends IPackageManager.Stub { this.uid = uid; if (srcArgs != null) { Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath())); - targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir); + targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir, instructionSet); } else { targetArgs = null; } @@ -7837,7 +8229,7 @@ public class PackageManagerService extends IPackageManager.Stub { } private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath, - String nativeLibraryPath) { + String nativeLibraryPath, String instructionSet) { final boolean isInAsec; if (installOnSd(flags)) { /* Apps on SD card are always in ASEC containers. */ @@ -7855,21 +8247,23 @@ public class PackageManagerService extends IPackageManager.Stub { if (isInAsec) { return new AsecInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath, - installOnSd(flags), installForwardLocked(flags)); + instructionSet, installOnSd(flags), installForwardLocked(flags)); } else { - return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath); + return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath, + instructionSet); } } // Used by package mover - private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir) { + private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir, + String instructionSet) { if (installOnSd(flags) || installForwardLocked(flags)) { String cid = getNextCodePath(packageURI.getPath(), pkgName, "/" + AsecInstallArgs.RES_FILE_NAME); - return new AsecInstallArgs(packageURI, cid, installOnSd(flags), + return new AsecInstallArgs(packageURI, cid, instructionSet, installOnSd(flags), installForwardLocked(flags)); } else { - return new FileInstallArgs(packageURI, pkgName, dataDir); + return new FileInstallArgs(packageURI, pkgName, dataDir, instructionSet); } } @@ -7881,16 +8275,18 @@ public class PackageManagerService extends IPackageManager.Stub { final String installerPackageName; final ManifestDigest manifestDigest; final UserHandle user; + final String instructionSet; InstallArgs(Uri packageURI, IPackageInstallObserver observer, int flags, String installerPackageName, ManifestDigest manifestDigest, - UserHandle user) { + UserHandle user, String instructionSet) { this.packageURI = packageURI; this.flags = flags; this.observer = observer; this.installerPackageName = installerPackageName; this.manifestDigest = manifestDigest; this.user = user; + this.instructionSet = instructionSet; } abstract void createCopyFile(); @@ -7946,11 +8342,12 @@ public class PackageManagerService extends IPackageManager.Stub { FileInstallArgs(InstallParams params) { super(params.getPackageUri(), params.observer, params.flags, params.installerPackageName, params.getManifestDigest(), - params.getUser()); + params.getUser(), null /* instruction set */); } - FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) { - super(null, null, 0, null, null, null); + FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath, + String instructionSet) { + super(null, null, 0, null, null, null, instructionSet); File codeFile = new File(fullCodePath); installDir = codeFile.getParentFile(); codeFileName = fullCodePath; @@ -7958,8 +8355,8 @@ public class PackageManagerService extends IPackageManager.Stub { libraryPath = nativeLibraryPath; } - FileInstallArgs(Uri packageURI, String pkgName, String dataDir) { - super(packageURI, null, 0, null, null, null); + FileInstallArgs(Uri packageURI, String pkgName, String dataDir, String instructionSet) { + super(packageURI, null, 0, null, null, null, instructionSet); installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir; String apkName = getNextCodePath(null, pkgName, ".apk"); codeFileName = new File(installDir, apkName + ".apk").getPath(); @@ -8065,7 +8462,7 @@ public class PackageManagerService extends IPackageManager.Stub { } try { int copyRet = copyNativeLibrariesForInternalApp(codeFile, nativeLibraryFile); - if (copyRet != PackageManager.INSTALL_SUCCEEDED) { + if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) { return copyRet; } } catch (IOException e) { @@ -8218,7 +8615,10 @@ public class PackageManagerService extends IPackageManager.Stub { void cleanUpResourcesLI() { String sourceDir = getCodePath(); if (cleanUp()) { - int retCode = mInstaller.rmdex(sourceDir); + if (instructionSet == null) { + throw new IllegalStateException("instructionSet == null"); + } + int retCode = mInstaller.rmdex(sourceDir, instructionSet); if (retCode < 0) { Slog.w(TAG, "Couldn't remove dex file for package: " + " at location " @@ -8282,14 +8682,14 @@ public class PackageManagerService extends IPackageManager.Stub { AsecInstallArgs(InstallParams params) { super(params.getPackageUri(), params.observer, params.flags, params.installerPackageName, params.getManifestDigest(), - params.getUser()); + params.getUser(), null /* instruction set */); } AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath, - boolean isExternal, boolean isForwardLocked) { + String instructionSet, boolean isExternal, boolean isForwardLocked) { super(null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0) | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), - null, null, null); + null, null, null, instructionSet); // Extract cid from fullCodePath int eidx = fullCodePath.lastIndexOf("/"); String subStr1 = fullCodePath.substring(0, eidx); @@ -8298,18 +8698,19 @@ public class PackageManagerService extends IPackageManager.Stub { setCachePath(subStr1); } - AsecInstallArgs(String cid, boolean isForwardLocked) { + AsecInstallArgs(String cid, String instructionSet, boolean isForwardLocked) { super(null, null, (isAsecExternal(cid) ? PackageManager.INSTALL_EXTERNAL : 0) | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), - null, null, null); + null, null, null, instructionSet); this.cid = cid; setCachePath(PackageHelper.getSdDir(cid)); } - AsecInstallArgs(Uri packageURI, String cid, boolean isExternal, boolean isForwardLocked) { + AsecInstallArgs(Uri packageURI, String cid, String instructionSet, + boolean isExternal, boolean isForwardLocked) { super(packageURI, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0) | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), - null, null, null); + null, null, null, instructionSet); this.cid = cid; } @@ -8490,7 +8891,10 @@ public class PackageManagerService extends IPackageManager.Stub { void cleanUpResourcesLI() { String sourceFile = getCodePath(); // Remove dex file - int retCode = mInstaller.rmdex(sourceFile); + if (instructionSet == null) { + throw new IllegalStateException("instructionSet == null"); + } + int retCode = mInstaller.rmdex(sourceFile, instructionSet); if (retCode < 0) { Slog.w(TAG, "Couldn't remove dex file for package: " + " at location " @@ -8871,7 +9275,8 @@ public class PackageManagerService extends IPackageManager.Stub { res.removedInfo.args = createInstallArgs(0, deletedPackage.applicationInfo.sourceDir, deletedPackage.applicationInfo.publicSourceDir, - deletedPackage.applicationInfo.nativeLibraryDir); + deletedPackage.applicationInfo.nativeLibraryDir, + getAppInstructionSet(deletedPackage.applicationInfo)); } else { res.removedInfo.args = null; } @@ -8920,7 +9325,8 @@ public class PackageManagerService extends IPackageManager.Stub { private int moveDexFilesLI(PackageParser.Package newPackage) { int retCode; if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) { - retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath); + retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath, + getAppInstructionSet(newPackage.applicationInfo)); if (retCode != 0) { if (mNoDexOpt) { /* @@ -9544,13 +9950,14 @@ public class PackageManagerService extends IPackageManager.Stub { } // writer synchronized (mPackages) { + PackageSetting ps = mSettings.mPackages.get(newPkg.packageName); + setInternalAppNativeLibraryPath(newPkg, ps); updatePermissionsLPw(newPkg.packageName, newPkg, UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG); if (applyUserRestrictions) { if (DEBUG_REMOVE) { Slog.d(TAG, "Propagating install state across reinstall"); } - PackageSetting ps = mSettings.mPackages.get(newPkg.packageName); for (int i = 0; i < allUserHandles.length; i++) { if (DEBUG_REMOVE) { Slog.d(TAG, " user " + allUserHandles[i] @@ -9584,7 +9991,8 @@ public class PackageManagerService extends IPackageManager.Stub { // Delete application code and resources if (deleteCodeAndResources && (outInfo != null)) { outInfo.args = createInstallArgs(packageFlagsToInstallFlags(ps), ps.codePathString, - ps.resourcePathString, ps.nativeLibraryPathString); + ps.resourcePathString, ps.nativeLibraryPathString, + getAppInstructionSetFromSettings(ps)); } return true; } @@ -9951,9 +10359,10 @@ public class PackageManagerService extends IPackageManager.Stub { boolean dataOnly = false; String libDirPath = null; String asecPath = null; + PackageSetting ps = null; synchronized (mPackages) { p = mPackages.get(packageName); - PackageSetting ps = mSettings.mPackages.get(packageName); + ps = mSettings.mPackages.get(packageName); if(p == null) { dataOnly = true; if((ps == null) || (ps.pkg == null)) { @@ -9984,7 +10393,8 @@ public class PackageManagerService extends IPackageManager.Stub { } } int res = mInstaller.getSizeInfo(packageName, userHandle, p.mPath, libDirPath, - publicSrcDir, asecPath, pStats); + publicSrcDir, asecPath, getAppInstructionSetFromSettings(ps), + pStats); if (res < 0) { return false; } @@ -11026,6 +11436,10 @@ public class PackageManagerService extends IPackageManager.Stub { */ public void scanAvailableAsecs() { updateExternalMediaStatusInner(true, false, false); + if (mShouldRestoreconData) { + SELinuxMMAC.setRestoreconDone(); + mShouldRestoreconData = false; + } } /* @@ -11081,7 +11495,9 @@ public class PackageManagerService extends IPackageManager.Stub { continue; } - final AsecInstallArgs args = new AsecInstallArgs(cid, isForwardLocked(ps)); + final AsecInstallArgs args = new AsecInstallArgs(cid, + getAppInstructionSetFromSettings(ps), + isForwardLocked(ps)); // The package status is changed only if the code path // matches between settings and the container id. if (ps.codePathString != null && ps.codePathString.equals(args.getCodePath())) { @@ -11396,15 +11812,17 @@ public class PackageManagerService extends IPackageManager.Stub { * anyway. */ if (returnCode != PackageManager.MOVE_SUCCEEDED) { - processPendingMove(new MoveParams(null, observer, 0, packageName, + processPendingMove(new MoveParams(null, observer, 0, packageName, null, null, -1, user), returnCode); } else { Message msg = mHandler.obtainMessage(INIT_COPY); + final String instructionSet = getAppInstructionSet(pkg.applicationInfo); InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir, - pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir); + pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir, + instructionSet); MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName, - pkg.applicationInfo.dataDir, pkg.applicationInfo.uid, user); + pkg.applicationInfo.dataDir, instructionSet, pkg.applicationInfo.uid, user); msg.obj = mp; mHandler.sendMessage(msg); } @@ -11471,8 +11889,17 @@ public class PackageManagerService extends IPackageManager.Stub { final File newNativeDir = new File(newNativePath); if (!isForwardLocked(pkg) && !isExternal(pkg)) { - NativeLibraryHelper.copyNativeBinariesIfNeededLI( - new File(newCodePath), newNativeDir); + // NOTE: We do not report any errors from the APK scan and library + // copy at this point. + NativeLibraryHelper.ApkHandle handle = + new NativeLibraryHelper.ApkHandle(newCodePath); + final int abi = NativeLibraryHelper.findSupportedAbi( + handle, Build.SUPPORTED_ABIS); + if (abi >= 0) { + NativeLibraryHelper.copyNativeBinariesIfNeededLI( + handle, newNativeDir, Build.SUPPORTED_ABIS[abi]); + } + handle.close(); } final int[] users = sUserManager.getUserIds(); for (int user : users) { diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index b447861..15df3d2 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -30,8 +30,8 @@ final class PackageSetting extends PackageSettingBase { SharedUserSetting sharedUser; PackageSetting(String name, String realName, File codePath, File resourcePath, - String nativeLibraryPathString, int pVersionCode, int pkgFlags) { - super(name, realName, codePath, resourcePath, nativeLibraryPathString, pVersionCode, + String nativeLibraryPathString, String requiredCpuAbiString, int pVersionCode, int pkgFlags) { + super(name, realName, codePath, resourcePath, nativeLibraryPathString, requiredCpuAbiString, pVersionCode, pkgFlags); } diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java index 7747c8f..ba95b9a 100644 --- a/services/core/java/com/android/server/pm/PackageSettingBase.java +++ b/services/core/java/com/android/server/pm/PackageSettingBase.java @@ -53,6 +53,7 @@ class PackageSettingBase extends GrantedPermissions { File resourcePath; String resourcePathString; String nativeLibraryPathString; + String requiredCpuAbiString; long timeStamp; long firstInstallTime; long lastUpdateTime; @@ -80,11 +81,11 @@ class PackageSettingBase extends GrantedPermissions { /* package name of the app that installed this package */ String installerPackageName; PackageSettingBase(String name, String realName, File codePath, File resourcePath, - String nativeLibraryPathString, int pVersionCode, int pkgFlags) { + String nativeLibraryPathString, String requiredCpuAbiString, int pVersionCode, int pkgFlags) { super(pkgFlags); this.name = name; this.realName = realName; - init(codePath, resourcePath, nativeLibraryPathString, pVersionCode); + init(codePath, resourcePath, nativeLibraryPathString, requiredCpuAbiString, pVersionCode); } /** @@ -101,6 +102,7 @@ class PackageSettingBase extends GrantedPermissions { resourcePath = base.resourcePath; resourcePathString = base.resourcePathString; nativeLibraryPathString = base.nativeLibraryPathString; + requiredCpuAbiString = base.requiredCpuAbiString; timeStamp = base.timeStamp; firstInstallTime = base.firstInstallTime; lastUpdateTime = base.lastUpdateTime; @@ -128,12 +130,13 @@ class PackageSettingBase extends GrantedPermissions { } void init(File codePath, File resourcePath, String nativeLibraryPathString, - int pVersionCode) { + String requiredCpuAbiString, int pVersionCode) { this.codePath = codePath; this.codePathString = codePath.toString(); this.resourcePath = resourcePath; this.resourcePathString = resourcePath.toString(); this.nativeLibraryPathString = nativeLibraryPathString; + this.requiredCpuAbiString = requiredCpuAbiString; this.versionCode = pVersionCode; } @@ -164,6 +167,7 @@ class PackageSettingBase extends GrantedPermissions { grantedPermissions = base.grantedPermissions; gids = base.gids; + requiredCpuAbiString = base.requiredCpuAbiString; timeStamp = base.timeStamp; firstInstallTime = base.firstInstallTime; lastUpdateTime = base.lastUpdateTime; diff --git a/services/core/java/com/android/server/pm/PendingPackage.java b/services/core/java/com/android/server/pm/PendingPackage.java index c17cc46..36c3a34 100644 --- a/services/core/java/com/android/server/pm/PendingPackage.java +++ b/services/core/java/com/android/server/pm/PendingPackage.java @@ -22,8 +22,8 @@ final class PendingPackage extends PackageSettingBase { final int sharedId; PendingPackage(String name, String realName, File codePath, File resourcePath, - String nativeLibraryPathString, int sharedId, int pVersionCode, int pkgFlags) { - super(name, realName, codePath, resourcePath, nativeLibraryPathString, pVersionCode, + String nativeLibraryPathString, String requiredCpuAbiString, int sharedId, int pVersionCode, int pkgFlags) { + super(name, realName, codePath, resourcePath, nativeLibraryPathString, requiredCpuAbiString, pVersionCode, pkgFlags); this.sharedId = sharedId; } diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java index 1d68afa..d70c725 100644 --- a/services/core/java/com/android/server/pm/SELinuxMMAC.java +++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java @@ -25,11 +25,15 @@ import android.util.Xml; import com.android.internal.util.XmlUtils; +import libcore.io.IoUtils; + import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.HashMap; @@ -60,6 +64,13 @@ public final class SELinuxMMAC { new File(Environment.getRootDirectory(), "etc/security/mac_permissions.xml"), null}; + // Location of seapp_contexts policy file. + private static final String SEAPP_CONTEXTS_FILE = "/seapp_contexts"; + + // Stores the hash of the last used seapp_contexts file. + private static final String SEAPP_HASH_FILE = + Environment.getDataDirectory().toString() + "/system/seapp_hash"; + // Signature policy stanzas static class Policy { private String seinfo; @@ -103,7 +114,6 @@ public final class SELinuxMMAC { /** * Parses an MMAC install policy from a predefined list of locations. - * @param none * @return boolean indicating whether an install policy was correctly parsed. */ public static boolean readInstallPolicy() { @@ -113,7 +123,7 @@ public final class SELinuxMMAC { /** * Parses an MMAC install policy given as an argument. - * @param File object representing the path of the policy. + * @param policyFile object representing the path of the policy. * @return boolean indicating whether the install policy was correctly parsed. */ public static boolean readInstallPolicy(File policyFile) { @@ -345,8 +355,7 @@ public final class SELinuxMMAC { /** * Labels a package based on an seinfo tag from install policy. * The label is attached to the ApplicationInfo instance of the package. - * @param PackageParser.Package object representing the package - * to labeled. + * @param pkg object representing the package to be labeled. * @return boolean which determines whether a non null seinfo label * was assigned to the package. A null value simply meaning that * no policy matched. @@ -391,4 +400,89 @@ public final class SELinuxMMAC { return (sDefaultSeinfo != null); } + + /** + * Determines if a recursive restorecon on /data/data and /data/user is needed. + * It does this by comparing the SHA-1 of the seapp_contexts file against the + * stored hash at /data/system/seapp_hash. + * + * @return Returns true if the restorecon should occur or false otherwise. + */ + public static boolean shouldRestorecon() { + // Any error with the seapp_contexts file should be fatal + byte[] currentHash = null; + try { + currentHash = returnHash(SEAPP_CONTEXTS_FILE); + } catch (IOException ioe) { + Slog.e(TAG, "Error with hashing seapp_contexts.", ioe); + return false; + } + + // Push past any error with the stored hash file + byte[] storedHash = null; + try { + storedHash = IoUtils.readFileAsByteArray(SEAPP_HASH_FILE); + } catch (IOException ioe) { + Slog.w(TAG, "Error opening " + SEAPP_HASH_FILE + ". Assuming first boot."); + } + + return (storedHash == null || !MessageDigest.isEqual(storedHash, currentHash)); + } + + /** + * Stores the SHA-1 of the seapp_contexts to /data/system/seapp_hash. + */ + public static void setRestoreconDone() { + try { + final byte[] currentHash = returnHash(SEAPP_CONTEXTS_FILE); + dumpHash(new File(SEAPP_HASH_FILE), currentHash); + } catch (IOException ioe) { + Slog.e(TAG, "Error with saving hash to " + SEAPP_HASH_FILE, ioe); + } + } + + /** + * Dump the contents of a byte array to a specified file. + * + * @param file The file that receives the byte array content. + * @param content A byte array that will be written to the specified file. + * @throws IOException if any failed I/O operation occured. + * Included is the failure to atomically rename the tmp + * file used in the process. + */ + private static void dumpHash(File file, byte[] content) throws IOException { + FileOutputStream fos = null; + File tmp = null; + try { + tmp = File.createTempFile("seapp_hash", ".journal", file.getParentFile()); + tmp.setReadable(true); + fos = new FileOutputStream(tmp); + fos.write(content); + fos.getFD().sync(); + if (!tmp.renameTo(file)) { + throw new IOException("Failure renaming " + file.getCanonicalPath()); + } + } finally { + if (tmp != null) { + tmp.delete(); + } + IoUtils.closeQuietly(fos); + } + } + + /** + * Return the SHA-1 of a file. + * + * @param file The path to the file given as a string. + * @return Returns the SHA-1 of the file as a byte array. + * @throws IOException if any failed I/O operations occured. + */ + private static byte[] returnHash(String file) throws IOException { + try { + final byte[] contents = IoUtils.readFileAsByteArray(file); + return MessageDigest.getInstance("SHA-1").digest(contents); + } catch (NoSuchAlgorithmException nsae) { + throw new RuntimeException(nsae); // impossible + } + } } diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 8f18b23..27ec1bf 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -36,6 +36,7 @@ import com.android.internal.util.JournaledFile; import com.android.internal.util.XmlUtils; import com.android.server.pm.PackageManagerService.DumpState; +import java.util.Collection; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -213,10 +214,10 @@ final class Settings { PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage, String realName, SharedUserSetting sharedUser, File codePath, File resourcePath, - String nativeLibraryPathString, int pkgFlags, UserHandle user, boolean add) { + String nativeLibraryPathString, String requiredCpuAbiString, int pkgFlags, UserHandle user, boolean add) { final String name = pkg.packageName; PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath, - resourcePath, nativeLibraryPathString, pkg.mVersionCode, pkgFlags, + resourcePath, nativeLibraryPathString, requiredCpuAbiString, pkg.mVersionCode, pkgFlags, user, add, true /* allowInstall */); return p; } @@ -262,6 +263,11 @@ final class Settings { return s; } + Collection<SharedUserSetting> getAllSharedUsersLPw() { + return mSharedUsers.values(); + } + + boolean disableSystemPackageLPw(String name) { final PackageSetting p = mPackages.get(name); if(p == null) { @@ -298,7 +304,7 @@ final class Settings { p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; } PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath, - p.nativeLibraryPathString, p.appId, p.versionCode, p.pkgFlags); + p.nativeLibraryPathString, p.requiredCpuAbiString, p.appId, p.versionCode, p.pkgFlags); mDisabledSysPackages.remove(name); return ret; } @@ -312,7 +318,7 @@ final class Settings { } PackageSetting addPackageLPw(String name, String realName, File codePath, File resourcePath, - String nativeLibraryPathString, int uid, int vc, int pkgFlags) { + String nativeLibraryPathString, String requiredCpuAbiString, int uid, int vc, int pkgFlags) { PackageSetting p = mPackages.get(name); if (p != null) { if (p.appId == uid) { @@ -322,7 +328,7 @@ final class Settings { "Adding duplicate package, keeping first: " + name); return null; } - p = new PackageSetting(name, realName, codePath, resourcePath, nativeLibraryPathString, + p = new PackageSetting(name, realName, codePath, resourcePath, nativeLibraryPathString, requiredCpuAbiString, vc, pkgFlags); p.appId = uid; if (addUserIdLPw(uid, p, name)) { @@ -391,10 +397,11 @@ final class Settings { private PackageSetting getPackageLPw(String name, PackageSetting origPackage, String realName, SharedUserSetting sharedUser, File codePath, File resourcePath, - String nativeLibraryPathString, int vc, int pkgFlags, + String nativeLibraryPathString, String requiredCpuAbiString, int vc, int pkgFlags, UserHandle installUser, boolean add, boolean allowInstall) { PackageSetting p = mPackages.get(name); if (p != null) { + p.requiredCpuAbiString = requiredCpuAbiString; if (!p.codePath.equals(codePath)) { // Check to see if its a disabled system app if ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) { @@ -438,7 +445,7 @@ final class Settings { if (origPackage != null) { // We are consuming the data from an existing package. p = new PackageSetting(origPackage.name, name, codePath, resourcePath, - nativeLibraryPathString, vc, pkgFlags); + nativeLibraryPathString, requiredCpuAbiString, vc, pkgFlags); if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package " + name + " is adopting original package " + origPackage.name); // Note that we will retain the new package's signature so @@ -455,7 +462,7 @@ final class Settings { p.setTimeStamp(codePath.lastModified()); } else { p = new PackageSetting(name, realName, codePath, resourcePath, - nativeLibraryPathString, vc, pkgFlags); + nativeLibraryPathString, requiredCpuAbiString, vc, pkgFlags); p.setTimeStamp(codePath.lastModified()); p.sharedUser = sharedUser; // If this is not a system app, it starts out stopped. @@ -581,6 +588,8 @@ final class Settings { && !nativeLibraryPath.equalsIgnoreCase(p.nativeLibraryPathString)) { p.nativeLibraryPathString = nativeLibraryPath; } + // Update the required Cpu Abi + p.requiredCpuAbiString = pkg.applicationInfo.requiredCpuAbi; // Update version code if needed if (pkg.mVersionCode != p.versionCode) { p.versionCode = pkg.mVersionCode; @@ -1427,6 +1436,7 @@ final class Settings { // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES: // system/core/run-as/run-as.c // system/core/sdcard/sdcard.c + // external/libselinux/src/android.c:package_info_init() // sb.setLength(0); sb.append(ai.packageName); @@ -1497,6 +1507,9 @@ final class Settings { if (pkg.nativeLibraryPathString != null) { serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString); } + if (pkg.requiredCpuAbiString != null) { + serializer.attribute(null, "requiredCpuAbi", pkg.requiredCpuAbiString); + } if (pkg.sharedUser == null) { serializer.attribute(null, "userId", Integer.toString(pkg.appId)); } else { @@ -1539,6 +1552,9 @@ final class Settings { if (pkg.nativeLibraryPathString != null) { serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString); } + if (pkg.requiredCpuAbiString != null) { + serializer.attribute(null, "requiredCpuAbi", pkg.requiredCpuAbiString); + } serializer.attribute(null, "flags", Integer.toString(pkg.pkgFlags)); serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp)); serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime)); @@ -1803,7 +1819,7 @@ final class Settings { if (idObj != null && idObj instanceof SharedUserSetting) { PackageSetting p = getPackageLPw(pp.name, null, pp.realName, (SharedUserSetting) idObj, pp.codePath, pp.resourcePath, - pp.nativeLibraryPathString, pp.versionCode, pp.pkgFlags, + pp.nativeLibraryPathString, pp.requiredCpuAbiString, pp.versionCode, pp.pkgFlags, null, true /* add */, false /* allowInstall */); if (p == null) { PackageManagerService.reportSettingsProblem(Log.WARN, @@ -2223,6 +2239,8 @@ final class Settings { String codePathStr = parser.getAttributeValue(null, "codePath"); String resourcePathStr = parser.getAttributeValue(null, "resourcePath"); String nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath"); + String requiredCpuAbiString = parser.getAttributeValue(null, "requiredCpuAbi"); + if (resourcePathStr == null) { resourcePathStr = codePathStr; } @@ -2242,7 +2260,7 @@ final class Settings { pkgFlags |= ApplicationInfo.FLAG_PRIVILEGED; } PackageSetting ps = new PackageSetting(name, realName, codePathFile, - new File(resourcePathStr), nativeLibraryPathStr, versionCode, pkgFlags); + new File(resourcePathStr), nativeLibraryPathStr, requiredCpuAbiString, versionCode, pkgFlags); String timeStampStr = parser.getAttributeValue(null, "ft"); if (timeStampStr != null) { try { @@ -2309,6 +2327,7 @@ final class Settings { String codePathStr = null; String resourcePathStr = null; String nativeLibraryPathStr = null; + String requiredCpuAbiString = null; String systemStr = null; String installerPackageName = null; String uidError = null; @@ -2328,6 +2347,8 @@ final class Settings { codePathStr = parser.getAttributeValue(null, "codePath"); resourcePathStr = parser.getAttributeValue(null, "resourcePath"); nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath"); + requiredCpuAbiString = parser.getAttributeValue(null, "requiredCpuAbi"); + version = parser.getAttributeValue(null, "version"); if (version != null) { try { @@ -2404,7 +2425,7 @@ final class Settings { + parser.getPositionDescription()); } else if (userId > 0) { packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr), - new File(resourcePathStr), nativeLibraryPathStr, userId, versionCode, + new File(resourcePathStr), nativeLibraryPathStr, requiredCpuAbiString, userId, versionCode, pkgFlags); if (PackageManagerService.DEBUG_SETTINGS) Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId=" @@ -2422,7 +2443,7 @@ final class Settings { userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0; if (userId > 0) { packageSetting = new PendingPackage(name.intern(), realName, new File( - codePathStr), new File(resourcePathStr), nativeLibraryPathStr, userId, + codePathStr), new File(resourcePathStr), nativeLibraryPathStr, requiredCpuAbiString, userId, versionCode, pkgFlags); packageSetting.setTimeStamp(timeStamp); packageSetting.firstInstallTime = firstInstallTime; @@ -2451,6 +2472,7 @@ final class Settings { packageSetting.uidError = "true".equals(uidError); packageSetting.installerPackageName = installerPackageName; packageSetting.nativeLibraryPathString = nativeLibraryPathStr; + packageSetting.requiredCpuAbiString = requiredCpuAbiString; // Handle legacy string here for single-user mode final String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED); if (enabledStr != null) { @@ -2950,6 +2972,7 @@ final class Settings { 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(" requiredCpuAbi="); pw.println(ps.requiredCpuAbiString); pw.print(prefix); pw.print(" versionCode="); pw.print(ps.versionCode); if (ps.pkg != null) { pw.print(" targetSdk="); pw.print(ps.pkg.applicationInfo.targetSdkVersion); diff --git a/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java b/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java index e430814..3c960c7 100644 --- a/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java +++ b/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java @@ -18,10 +18,10 @@ package com.android.server.updates; import android.content.Context; import android.content.Intent; -import android.os.FileUtils; -import android.os.SELinux; import android.os.SystemProperties; import android.provider.Settings; +import android.system.ErrnoException; +import android.system.Os; import android.util.Base64; import android.util.Slog; @@ -30,9 +30,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import libcore.io.ErrnoException; import libcore.io.IoUtils; -import libcore.io.Libcore; public class SELinuxPolicyInstallReceiver extends ConfigUpdateInstallReceiver { @@ -112,16 +110,16 @@ public class SELinuxPolicyInstallReceiver extends ConfigUpdateInstallReceiver { File update = new File(updateDir.getParentFile(), "update"); File tmp = new File(updateDir.getParentFile(), "tmp"); if (current.exists()) { - Libcore.os.symlink(updateDir.getPath(), update.getPath()); - Libcore.os.rename(update.getPath(), current.getPath()); + Os.symlink(updateDir.getPath(), update.getPath()); + Os.rename(update.getPath(), current.getPath()); } else { - Libcore.os.symlink(updateDir.getPath(), current.getPath()); + Os.symlink(updateDir.getPath(), current.getPath()); } contexts.mkdirs(); backupContexts(contexts); copyUpdate(contexts); - Libcore.os.symlink(contexts.getPath(), tmp.getPath()); - Libcore.os.rename(tmp.getPath(), current.getPath()); + Os.symlink(contexts.getPath(), tmp.getPath()); + Os.rename(tmp.getPath(), current.getPath()); SystemProperties.set("selinux.reload_policy", "1"); } diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index e630737..f79896b 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -199,7 +199,8 @@ class ScreenRotationAnimation { } public ScreenRotationAnimation(Context context, DisplayContent displayContent, - SurfaceSession session, boolean inTransaction, boolean forceDefaultOrientation) { + SurfaceSession session, boolean inTransaction, boolean forceDefaultOrientation, + boolean isSecure) { mContext = context; mDisplayContent = displayContent; displayContent.getLogicalDisplayRect(mOriginalDisplayRect); @@ -241,16 +242,21 @@ class ScreenRotationAnimation { try { try { + int flags = SurfaceControl.HIDDEN; + if (isSecure) { + flags |= SurfaceControl.SECURE; + } + if (WindowManagerService.DEBUG_SURFACE_TRACE) { mSurfaceControl = new SurfaceTrace(session, "ScreenshotSurface", mWidth, mHeight, - PixelFormat.OPAQUE, SurfaceControl.HIDDEN); + PixelFormat.OPAQUE, flags); Slog.w(TAG, "ScreenRotationAnimation ctor: displayOffset=" + mOriginalDisplayRect.toShortString()); } else { mSurfaceControl = new SurfaceControl(session, "ScreenshotSurface", mWidth, mHeight, - PixelFormat.OPAQUE, SurfaceControl.HIDDEN); + PixelFormat.OPAQUE, flags); } // capture a screenshot into the surface we just created Surface sur = new Surface(); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 081cffd..6cdbdeb 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -3543,8 +3543,9 @@ public class WindowManagerService extends IWindowManager.Stub Task newTask = mTaskIdToTask.get(groupId); if (newTask == null) { newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken); + } else { + newTask.mAppTokens.add(atoken); } - newTask.mAppTokens.add(atoken); } } @@ -10028,10 +10029,22 @@ public class WindowManagerService extends IWindowManager.Stub screenRotationAnimation.kill(); } + // Check whether the current screen contains any secure content. + boolean isSecure = false; + final WindowList windows = getDefaultWindowListLocked(); + final int N = windows.size(); + for (int i = 0; i < N; i++) { + WindowState ws = windows.get(i); + if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) { + isSecure = true; + break; + } + } + // TODO(multidisplay): rotation on main screen only. displayContent.updateDisplayInfo(); screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, - mFxSession, inTransaction, mPolicy.isDefaultOrientationForced()); + mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure); mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); } } diff --git a/services/core/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp index 342515b..a58b00bce 100644 --- a/services/core/jni/com_android_server_AlarmManagerService.cpp +++ b/services/core/jni/com_android_server_AlarmManagerService.cpp @@ -36,6 +36,7 @@ #include <unistd.h> #include <linux/ioctl.h> #include <linux/android_alarm.h> +#include <linux/rtc.h> namespace android { @@ -58,6 +59,7 @@ public: virtual ~AlarmImpl(); virtual int set(int type, struct timespec *ts) = 0; + virtual int setTime(struct timeval *tv) = 0; virtual int waitForAlarm() = 0; protected: @@ -71,6 +73,7 @@ public: AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { } int set(int type, struct timespec *ts); + int setTime(struct timeval *tv); int waitForAlarm(); }; @@ -82,6 +85,7 @@ public: ~AlarmImplTimerFd(); int set(int type, struct timespec *ts); + int setTime(struct timeval *tv); int waitForAlarm(); private: @@ -107,6 +111,19 @@ int AlarmImplAlarmDriver::set(int type, struct timespec *ts) return ioctl(fds[0], ANDROID_ALARM_SET(type), ts); } +int AlarmImplAlarmDriver::setTime(struct timeval *tv) +{ + struct timespec ts; + int res; + + ts.tv_sec = tv->tv_sec; + ts.tv_nsec = tv->tv_usec * 1000; + res = ioctl(fds[0], ANDROID_ALARM_SET_RTC, &ts); + if (res < 0) + ALOGV("ANDROID_ALARM_SET_RTC ioctl failed: %s\n", strerror(errno)); + return res; +} + int AlarmImplAlarmDriver::waitForAlarm() { return ioctl(fds[0], ANDROID_ALARM_WAIT); @@ -140,6 +157,50 @@ int AlarmImplTimerFd::set(int type, struct timespec *ts) return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL); } +int AlarmImplTimerFd::setTime(struct timeval *tv) +{ + struct rtc_time rtc; + struct tm tm, *gmtime_res; + int fd; + int res; + + res = settimeofday(tv, NULL); + if (res < 0) { + ALOGV("settimeofday() failed: %s\n", strerror(errno)); + return -1; + } + + fd = open("/dev/rtc0", O_RDWR); + if (fd < 0) { + ALOGV("Unable to open RTC driver: %s\n", strerror(errno)); + return res; + } + + gmtime_res = gmtime_r(&tv->tv_sec, &tm); + if (!gmtime_res) { + ALOGV("gmtime_r() failed: %s\n", strerror(errno)); + res = -1; + goto done; + } + + memset(&rtc, 0, sizeof(rtc)); + rtc.tm_sec = tm.tm_sec; + rtc.tm_min = tm.tm_min; + rtc.tm_hour = tm.tm_hour; + rtc.tm_mday = tm.tm_mday; + rtc.tm_mon = tm.tm_mon; + rtc.tm_year = tm.tm_year; + rtc.tm_wday = tm.tm_wday; + rtc.tm_yday = tm.tm_yday; + rtc.tm_isdst = tm.tm_isdst; + res = ioctl(fd, RTC_SET_TIME, &rtc); + if (res < 0) + ALOGV("RTC_SET_TIME ioctl failed: %s\n", strerror(errno)); +done: + close(fd); + return res; +} + int AlarmImplTimerFd::waitForAlarm() { epoll_event events[N_ANDROID_TIMERFDS]; @@ -168,6 +229,30 @@ int AlarmImplTimerFd::waitForAlarm() return result; } +static jint android_server_AlarmManagerService_setKernelTime(JNIEnv*, jobject, jlong nativeData, jlong millis) +{ + AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData); + struct timeval tv; + int ret; + + if (millis <= 0 || millis / 1000LL >= INT_MAX) { + return -1; + } + + tv.tv_sec = (time_t) (millis / 1000LL); + tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL); + + ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec); + + ret = impl->setTime(&tv); + + if(ret < 0) { + ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno)); + ret = -1; + } + return ret; +} + static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest) { struct timezone tz; @@ -280,7 +365,9 @@ static void android_server_AlarmManagerService_set(JNIEnv*, jobject, jlong nativ int result = impl->set(type, &ts); if (result < 0) { - ALOGE("Unable to set alarm to %lld.%09lld: %s\n", seconds, nanoseconds, strerror(errno)); + ALOGE("Unable to set alarm to %lld.%09lld: %s\n", + static_cast<long long>(seconds), + static_cast<long long>(nanoseconds), strerror(errno)); } } @@ -309,6 +396,7 @@ static JNINativeMethod sMethods[] = { {"close", "(J)V", (void*)android_server_AlarmManagerService_close}, {"set", "(JIJJ)V", (void*)android_server_AlarmManagerService_set}, {"waitForAlarm", "(J)I", (void*)android_server_AlarmManagerService_waitForAlarm}, + {"setKernelTime", "(JJ)I", (void*)android_server_AlarmManagerService_setKernelTime}, {"setKernelTimezone", "(JI)I", (void*)android_server_AlarmManagerService_setKernelTimezone}, }; diff --git a/services/core/jni/com_android_server_AssetAtlasService.cpp b/services/core/jni/com_android_server_AssetAtlasService.cpp index 4a1b55d..163692b 100644 --- a/services/core/jni/com_android_server_AssetAtlasService.cpp +++ b/services/core/jni/com_android_server_AssetAtlasService.cpp @@ -73,7 +73,7 @@ static inline void swapCanvasPtr(JNIEnv* env, jobject canvasObj, SkCanvas* newCa SkSafeUnref(previousCanvas); } -static SkBitmap* com_android_server_AssetAtlasService_acquireCanvas(JNIEnv* env, jobject, +static jlong com_android_server_AssetAtlasService_acquireCanvas(JNIEnv* env, jobject, jobject canvas, jint width, jint height) { SkBitmap* bitmap = new SkBitmap; @@ -84,12 +84,13 @@ static SkBitmap* com_android_server_AssetAtlasService_acquireCanvas(JNIEnv* env, SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (*bitmap)); swapCanvasPtr(env, canvas, nativeCanvas); - return bitmap; + return reinterpret_cast<jlong>(bitmap); } static void com_android_server_AssetAtlasService_releaseCanvas(JNIEnv* env, jobject, - jobject canvas, SkBitmap* bitmap) { + jobject canvas, jlong bitmapHandle) { + SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); SkCanvas* nativeCanvas = SkNEW(SkCanvas); swapCanvasPtr(env, canvas, nativeCanvas); @@ -108,21 +109,22 @@ static void com_android_server_AssetAtlasService_releaseCanvas(JNIEnv* env, jobj return result; static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject, - jobject graphicBuffer, SkBitmap* bitmap) { + jobject graphicBuffer, jlong bitmapHandle) { + SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); // The goal of this method is to copy the bitmap into the GraphicBuffer // using the GPU to swizzle the texture content sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer)); if (buffer != NULL) { EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (display == EGL_NO_DISPLAY) return false; + if (display == EGL_NO_DISPLAY) return JNI_FALSE; EGLint major; EGLint minor; if (!eglInitialize(display, &major, &minor)) { ALOGW("Could not initialize EGL"); - return false; + return JNI_FALSE; } // We're going to use a 1x1 pbuffer surface later on @@ -143,13 +145,13 @@ static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject ALOGW("Could not select EGL configuration"); eglReleaseThread(); eglTerminate(display); - return false; + return JNI_FALSE; } if (configCount <= 0) { ALOGW("Could not find EGL configuration"); eglReleaseThread(); eglTerminate(display); - return false; + return JNI_FALSE; } // These objects are initialized below but the default "null" @@ -164,7 +166,7 @@ static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject EGLContext context = eglCreateContext(display, configs[0], EGL_NO_CONTEXT, attrs); if (context == EGL_NO_CONTEXT) { ALOGW("Could not create EGL context"); - CLEANUP_GL_AND_RETURN(false); + CLEANUP_GL_AND_RETURN(JNI_FALSE); } // Create the 1x1 pbuffer @@ -172,12 +174,12 @@ static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject surface = eglCreatePbufferSurface(display, configs[0], surfaceAttrs); if (surface == EGL_NO_SURFACE) { ALOGW("Could not create EGL surface"); - CLEANUP_GL_AND_RETURN(false); + CLEANUP_GL_AND_RETURN(JNI_FALSE); } if (!eglMakeCurrent(display, surface, surface, context)) { ALOGW("Could not change current EGL context"); - CLEANUP_GL_AND_RETURN(false); + CLEANUP_GL_AND_RETURN(JNI_FALSE); } // We use an EGLImage to access the content of the GraphicBuffer @@ -188,7 +190,7 @@ static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttrs); if (image == EGL_NO_IMAGE_KHR) { ALOGW("Could not create EGL image"); - CLEANUP_GL_AND_RETURN(false); + CLEANUP_GL_AND_RETURN(JNI_FALSE); } glGenTextures(1, &texture); @@ -196,7 +198,7 @@ static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); if (glGetError() != GL_NO_ERROR) { ALOGW("Could not create/bind texture"); - CLEANUP_GL_AND_RETURN(false); + CLEANUP_GL_AND_RETURN(JNI_FALSE); } // Upload the content of the bitmap in the GraphicBuffer @@ -205,7 +207,7 @@ static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels()); if (glGetError() != GL_NO_ERROR) { ALOGW("Could not upload to texture"); - CLEANUP_GL_AND_RETURN(false); + CLEANUP_GL_AND_RETURN(JNI_FALSE); } // The fence is used to wait for the texture upload to finish @@ -214,7 +216,7 @@ static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject fence = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, NULL); if (fence == EGL_NO_SYNC_KHR) { ALOGW("Could not create sync fence %#x", eglGetError()); - CLEANUP_GL_AND_RETURN(false); + CLEANUP_GL_AND_RETURN(JNI_FALSE); } // The flag EGL_SYNC_FLUSH_COMMANDS_BIT_KHR will trigger a @@ -223,13 +225,13 @@ static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, FENCE_TIMEOUT); if (waitStatus != EGL_CONDITION_SATISFIED_KHR) { ALOGW("Failed to wait for the fence %#x", eglGetError()); - CLEANUP_GL_AND_RETURN(false); + CLEANUP_GL_AND_RETURN(JNI_FALSE); } - CLEANUP_GL_AND_RETURN(true); + CLEANUP_GL_AND_RETURN(JNI_TRUE); } - return false; + return JNI_FALSE; } // ---------------------------------------------------------------------------- @@ -247,11 +249,11 @@ static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject const char* const kClassPathName = "com/android/server/AssetAtlasService"; static JNINativeMethod gMethods[] = { - { "nAcquireAtlasCanvas", "(Landroid/graphics/Canvas;II)I", + { "nAcquireAtlasCanvas", "(Landroid/graphics/Canvas;II)J", (void*) com_android_server_AssetAtlasService_acquireCanvas }, - { "nReleaseAtlasCanvas", "(Landroid/graphics/Canvas;I)V", + { "nReleaseAtlasCanvas", "(Landroid/graphics/Canvas;J)V", (void*) com_android_server_AssetAtlasService_releaseCanvas }, - { "nUploadAtlas", "(Landroid/view/GraphicBuffer;I)Z", + { "nUploadAtlas", "(Landroid/view/GraphicBuffer;J)Z", (void*) com_android_server_AssetAtlasService_upload }, }; diff --git a/services/core/jni/com_android_server_ConsumerIrService.cpp b/services/core/jni/com_android_server_ConsumerIrService.cpp index 004c0aa..3a50ff7 100644 --- a/services/core/jni/com_android_server_ConsumerIrService.cpp +++ b/services/core/jni/com_android_server_ConsumerIrService.cpp @@ -29,7 +29,7 @@ namespace android { -static jint halOpen(JNIEnv *env, jobject obj) { +static jlong halOpen(JNIEnv *env, jobject obj) { hw_module_t const* module; consumerir_device_t *dev; int err; @@ -47,10 +47,10 @@ static jint halOpen(JNIEnv *env, jobject obj) { return 0; } - return reinterpret_cast<jint>(dev); + return reinterpret_cast<jlong>(dev); } -static jint halTransmit(JNIEnv *env, jobject obj, jint halObject, +static jint halTransmit(JNIEnv *env, jobject obj, jlong halObject, jint carrierFrequency, jintArray pattern) { int ret; @@ -67,8 +67,8 @@ static jint halTransmit(JNIEnv *env, jobject obj, jint halObject, } static jintArray halGetCarrierFrequencies(JNIEnv *env, jobject obj, - jint halObject) { - consumerir_device_t *dev = (consumerir_device_t *) halObject; + jlong halObject) { + consumerir_device_t *dev = reinterpret_cast<consumerir_device_t*>(halObject); consumerir_freq_range_t *ranges; int len; @@ -101,9 +101,9 @@ static jintArray halGetCarrierFrequencies(JNIEnv *env, jobject obj, } static JNINativeMethod method_table[] = { - { "halOpen", "()I", (void *)halOpen }, - { "halTransmit", "(II[I)I", (void *)halTransmit }, - { "halGetCarrierFrequencies", "(I)[I", (void *)halGetCarrierFrequencies}, + { "halOpen", "()J", (void *)halOpen }, + { "halTransmit", "(JI[I)I", (void *)halTransmit }, + { "halGetCarrierFrequencies", "(J)[I", (void *)halGetCarrierFrequencies}, }; int register_android_server_ConsumerIrService(JNIEnv *env) { diff --git a/services/core/jni/com_android_server_UsbHostManager.cpp b/services/core/jni/com_android_server_UsbHostManager.cpp index f1fa6cf..fc6de60 100644 --- a/services/core/jni/com_android_server_UsbHostManager.cpp +++ b/services/core/jni/com_android_server_UsbHostManager.cpp @@ -163,8 +163,10 @@ static jobject android_server_UsbHostManager_openDevice(JNIEnv *env, jobject thi return NULL; int fd = usb_device_get_fd(device); - if (fd < 0) + if (fd < 0) { + usb_device_close(device); return NULL; + } int newFD = dup(fd); usb_device_close(device); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 8968725..6845e8c 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -51,6 +51,7 @@ import android.view.WindowManager; import com.android.internal.R; import com.android.internal.os.BinderInternal; +import com.android.internal.os.Zygote; import com.android.internal.os.SamplingProfilerIntegration; import com.android.server.accessibility.AccessibilityManagerService; import com.android.server.accounts.AccountManagerService; @@ -84,7 +85,6 @@ import com.android.server.wifi.WifiService; import com.android.server.wm.WindowManagerService; import dalvik.system.VMRuntime; -import dalvik.system.Zygote; import java.io.File; import java.util.Timer; @@ -167,7 +167,7 @@ public final class SystemServer { // had to fallback to a different runtime because it is // running as root and we need to be the system user to set // the property. http://b/11463182 - SystemProperties.set("persist.sys.dalvik.vm.lib", VMRuntime.getRuntime().vmLibrary()); + SystemProperties.set("persist.sys.dalvik.vm.lib.1", VMRuntime.getRuntime().vmLibrary()); // Enable the sampling profiler. if (SamplingProfilerIntegration.isEnabled()) { @@ -911,8 +911,6 @@ public final class SystemServer { final boolean safeMode = wm.detectSafeMode(); if (safeMode) { mActivityManagerService.enterSafeMode(); - // Post the safe mode state in the Zygote class - Zygote.systemInSafeMode = true; // Disable the JIT for the system_server process VMRuntime.getRuntime().disableJitCompilation(); } else { diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index 76a8d17..5d22ffc 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -594,14 +594,19 @@ public class UsbDeviceManager { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); intent.putExtra("state", (enabled ? 1 : 0)); if (enabled) { + Scanner scanner = null; try { - Scanner scanner = new Scanner(new File(AUDIO_SOURCE_PCM_PATH)); + scanner = new Scanner(new File(AUDIO_SOURCE_PCM_PATH)); int card = scanner.nextInt(); int device = scanner.nextInt(); intent.putExtra("card", card); intent.putExtra("device", device); } catch (FileNotFoundException e) { Slog.e(TAG, "could not open audio source PCM file", e); + } finally { + if (scanner != null) { + scanner.close(); + } } } mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); |