diff options
13 files changed, 482 insertions, 474 deletions
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index e8227088b7a9..e1a2aa96c36c 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -881,6 +881,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { /** * @hide */ + public boolean isForwardLocked() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0; + } + + /** + * @hide + */ @Override protected ApplicationInfo getApplicationInfo() { return this; } diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 77dc27aee9e5..4d9445df250a 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -4431,6 +4431,13 @@ public class PackageParser { return false; } + /** + * @hide + */ + public boolean isForwardLocked() { + return applicationInfo.isForwardLocked(); + } + public String toString() { return "Package{" + Integer.toHexString(System.identityHashCode(this)) diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java index 572cca2ff229..47644f9d1571 100644 --- a/core/java/android/widget/VideoView.java +++ b/core/java/android/widget/VideoView.java @@ -311,6 +311,8 @@ public class VideoView extends SurfaceView mMediaPlayer = null; mCurrentState = STATE_IDLE; mTargetState = STATE_IDLE; + AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + am.abandonAudioFocus(null); } } @@ -319,12 +321,13 @@ public class VideoView extends SurfaceView // not ready for playback just yet, will try again later return; } - AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); - am.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); - // we shouldn't clear the target state, because somebody might have // called start() previously release(false); + + AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + am.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); + try { mMediaPlayer = new MediaPlayer(); // TODO: create SubtitleController in MediaPlayer, but we need @@ -650,6 +653,8 @@ public class VideoView extends SurfaceView if (cleartargetstate) { mTargetState = STATE_IDLE; } + AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + am.abandonAudioFocus(null); } } diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 620f0ace2827..ed6ce875f1d3 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -58,7 +58,7 @@ import java.util.Iterator; */ public class AudioManager { - private final Context mContext; + private final Context mApplicationContext; private long mVolumeKeyUpTime; private final boolean mUseMasterVolume; private final boolean mUseVolumeKeySounds; @@ -641,12 +641,12 @@ public class AudioManager { * @hide */ public AudioManager(Context context) { - mContext = context; - mUseMasterVolume = mContext.getResources().getBoolean( + mApplicationContext = context.getApplicationContext(); + mUseMasterVolume = mApplicationContext.getResources().getBoolean( com.android.internal.R.bool.config_useMasterVolume); - mUseVolumeKeySounds = mContext.getResources().getBoolean( + mUseVolumeKeySounds = mApplicationContext.getResources().getBoolean( com.android.internal.R.bool.config_useVolumeKeySounds); - mUseFixedVolume = mContext.getResources().getBoolean( + mUseFixedVolume = mApplicationContext.getResources().getBoolean( com.android.internal.R.bool.config_useFixedVolume); sAudioPortEventHandler.init(); } @@ -685,7 +685,7 @@ public class AudioManager { * or {@link KeyEvent#KEYCODE_MEDIA_AUDIO_TRACK}. */ public void dispatchMediaKeyEvent(KeyEvent keyEvent) { - MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext); + MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mApplicationContext); helper.sendMediaButtonEvent(keyEvent, false); } @@ -746,7 +746,8 @@ public class AudioManager { break; case KeyEvent.KEYCODE_VOLUME_MUTE: if (event.getRepeatCount() == 0) { - MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(event, false); + MediaSessionLegacyHelper.getHelper(mApplicationContext) + .sendVolumeKeyEvent(event, false); } break; } @@ -778,7 +779,8 @@ public class AudioManager { mVolumeKeyUpTime = SystemClock.uptimeMillis(); break; case KeyEvent.KEYCODE_VOLUME_MUTE: - MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(event, false); + MediaSessionLegacyHelper.getHelper(mApplicationContext) + .sendVolumeKeyEvent(event, false); break; } } @@ -823,10 +825,11 @@ public class AudioManager { IAudioService service = getService(); try { if (mUseMasterVolume) { - service.adjustMasterVolume(direction, flags, mContext.getOpPackageName()); + service.adjustMasterVolume(direction, flags, + mApplicationContext.getOpPackageName()); } else { service.adjustStreamVolume(streamType, direction, flags, - mContext.getOpPackageName()); + mApplicationContext.getOpPackageName()); } } catch (RemoteException e) { Log.e(TAG, "Dead object in adjustStreamVolume", e); @@ -856,9 +859,11 @@ public class AudioManager { IAudioService service = getService(); try { if (mUseMasterVolume) { - service.adjustMasterVolume(direction, flags, mContext.getOpPackageName()); + service.adjustMasterVolume(direction, flags, + mApplicationContext.getOpPackageName()); } else { - MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext); + MediaSessionLegacyHelper helper = + MediaSessionLegacyHelper.getHelper(mApplicationContext); helper.sendAdjustVolumeBy(USE_DEFAULT_STREAM_TYPE, direction, flags); } } catch (RemoteException e) { @@ -890,9 +895,11 @@ public class AudioManager { IAudioService service = getService(); try { if (mUseMasterVolume) { - service.adjustMasterVolume(direction, flags, mContext.getOpPackageName()); + service.adjustMasterVolume(direction, flags, + mApplicationContext.getOpPackageName()); } else { - MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext); + MediaSessionLegacyHelper helper = + MediaSessionLegacyHelper.getHelper(mApplicationContext); helper.sendAdjustVolumeBy(suggestedStreamType, direction, flags); } } catch (RemoteException e) { @@ -912,7 +919,7 @@ public class AudioManager { public void adjustMasterVolume(int steps, int flags) { IAudioService service = getService(); try { - service.adjustMasterVolume(steps, flags, mContext.getOpPackageName()); + service.adjustMasterVolume(steps, flags, mApplicationContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "Dead object in adjustMasterVolume", e); } @@ -1053,7 +1060,7 @@ public class AudioManager { } IAudioService service = getService(); try { - service.setRingerModeExternal(ringerMode, mContext.getOpPackageName()); + service.setRingerModeExternal(ringerMode, mApplicationContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "Dead object in setRingerMode", e); } @@ -1075,9 +1082,10 @@ public class AudioManager { IAudioService service = getService(); try { if (mUseMasterVolume) { - service.setMasterVolume(index, flags, mContext.getOpPackageName()); + service.setMasterVolume(index, flags, mApplicationContext.getOpPackageName()); } else { - service.setStreamVolume(streamType, index, flags, mContext.getOpPackageName()); + service.setStreamVolume(streamType, index, flags, + mApplicationContext.getOpPackageName()); } } catch (RemoteException e) { Log.e(TAG, "Dead object in setStreamVolume", e); @@ -1143,7 +1151,7 @@ public class AudioManager { public void setMasterVolume(int index, int flags) { IAudioService service = getService(); try { - service.setMasterVolume(index, flags, mContext.getOpPackageName()); + service.setMasterVolume(index, flags, mApplicationContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "Dead object in setMasterVolume", e); } @@ -1244,7 +1252,7 @@ public class AudioManager { public void setMasterMute(boolean state, int flags) { IAudioService service = getService(); try { - service.setMasterMute(state, flags, mContext.getOpPackageName(), mICallBack); + service.setMasterMute(state, flags, mApplicationContext.getOpPackageName(), mICallBack); } catch (RemoteException e) { Log.e(TAG, "Dead object in setMasterMute", e); } @@ -1482,7 +1490,7 @@ public class AudioManager { * @see #startBluetoothSco() */ public boolean isBluetoothScoAvailableOffCall() { - return mContext.getResources().getBoolean( + return mApplicationContext.getResources().getBoolean( com.android.internal.R.bool.config_bluetooth_sco_off_call); } @@ -1534,7 +1542,8 @@ public class AudioManager { public void startBluetoothSco(){ IAudioService service = getService(); try { - service.startBluetoothSco(mICallBack, mContext.getApplicationInfo().targetSdkVersion); + service.startBluetoothSco(mICallBack, + mApplicationContext.getApplicationInfo().targetSdkVersion); } catch (RemoteException e) { Log.e(TAG, "Dead object in startBluetoothSco", e); } @@ -1682,7 +1691,7 @@ public class AudioManager { public void setMicrophoneMute(boolean on){ IAudioService service = getService(); try { - service.setMicrophoneMute(on, mContext.getOpPackageName()); + service.setMicrophoneMute(on, mApplicationContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "Dead object in setMicrophoneMute", e); } @@ -2113,7 +2122,7 @@ public class AudioManager { * Settings has an in memory cache, so this is fast. */ private boolean querySoundEffectsEnabled(int user) { - return Settings.System.getIntForUser(mContext.getContentResolver(), + return Settings.System.getIntForUser(mApplicationContext.getContentResolver(), Settings.System.SOUND_EFFECTS_ENABLED, 0, user) != 0; } @@ -2525,7 +2534,7 @@ public class AudioManager { try { status = service.requestAudioFocus(requestAttributes, durationHint, mICallBack, mAudioFocusDispatcher, getIdForAudioFocusListener(l), - mContext.getOpPackageName() /* package name */, flags, + mApplicationContext.getOpPackageName() /* package name */, flags, ap != null ? ap.cb() : null); } catch (RemoteException e) { Log.e(TAG, "Can't call requestAudioFocus() on AudioService:", e); @@ -2550,7 +2559,7 @@ public class AudioManager { .setInternalLegacyStreamType(streamType).build(), durationHint, mICallBack, null, MediaFocusControl.IN_VOICE_COMM_FOCUS_ID, - mContext.getOpPackageName(), + mApplicationContext.getOpPackageName(), AUDIOFOCUS_FLAG_LOCK, null /* policy token */); } catch (RemoteException e) { @@ -2619,7 +2628,7 @@ public class AudioManager { if (eventReceiver == null) { return; } - if (!eventReceiver.getPackageName().equals(mContext.getPackageName())) { + if (!eventReceiver.getPackageName().equals(mApplicationContext.getPackageName())) { Log.e(TAG, "registerMediaButtonEventReceiver() error: " + "receiver and context package names don't match"); return; @@ -2628,7 +2637,7 @@ public class AudioManager { Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); // the associated intent will be handled by the component being registered mediaButtonIntent.setComponent(eventReceiver); - PendingIntent pi = PendingIntent.getBroadcast(mContext, + PendingIntent pi = PendingIntent.getBroadcast(mApplicationContext, 0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/); registerMediaButtonIntent(pi, eventReceiver); } @@ -2662,8 +2671,8 @@ public class AudioManager { Log.e(TAG, "Cannot call registerMediaButtonIntent() with a null parameter"); return; } - MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext); - helper.addMediaButtonListener(pi, eventReceiver, mContext); + MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mApplicationContext); + helper.addMediaButtonListener(pi, eventReceiver, mApplicationContext); } /** @@ -2681,7 +2690,7 @@ public class AudioManager { Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); // the associated intent will be handled by the component being registered mediaButtonIntent.setComponent(eventReceiver); - PendingIntent pi = PendingIntent.getBroadcast(mContext, + PendingIntent pi = PendingIntent.getBroadcast(mApplicationContext, 0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/); unregisterMediaButtonIntent(pi); } @@ -2704,7 +2713,7 @@ public class AudioManager { * @hide */ public void unregisterMediaButtonIntent(PendingIntent pi) { - MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext); + MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mApplicationContext); helper.removeMediaButtonListener(pi); } @@ -2721,7 +2730,7 @@ public class AudioManager { if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) { return; } - rcClient.registerWithSession(MediaSessionLegacyHelper.getHelper(mContext)); + rcClient.registerWithSession(MediaSessionLegacyHelper.getHelper(mApplicationContext)); } /** @@ -2736,7 +2745,7 @@ public class AudioManager { if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) { return; } - rcClient.unregisterWithSession(MediaSessionLegacyHelper.getHelper(mContext)); + rcClient.unregisterWithSession(MediaSessionLegacyHelper.getHelper(mApplicationContext)); } /** @@ -3397,7 +3406,7 @@ public class AudioManager { */ public void setRingerModeInternal(int ringerMode) { try { - getService().setRingerModeInternal(ringerMode, mContext.getOpPackageName()); + getService().setRingerModeInternal(ringerMode, mApplicationContext.getOpPackageName()); } catch (RemoteException e) { Log.w(TAG, "Error calling setRingerModeInternal", e); } diff --git a/rs/java/android/renderscript/Path.java b/rs/java/android/renderscript/Path.java deleted file mode 100644 index f3502aacbd64..000000000000 --- a/rs/java/android/renderscript/Path.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.renderscript; - -/** - * @hide - * - */ -public class Path extends BaseObj { - - public enum Primitive { - QUADRATIC_BEZIER(0), - CUBIC_BEZIER(1); - - int mID; - Primitive(int id) { - mID = id; - } - } - - Allocation mVertexBuffer; - Allocation mLoopBuffer; - Primitive mPrimitive; - float mQuality; - boolean mCoverageToAlpha; - - Path(long id, RenderScript rs, Primitive p, Allocation vtx, Allocation loop, float q) { - super(id, rs); - mVertexBuffer = vtx; - mLoopBuffer = loop; - mPrimitive = p; - mQuality = q; - } - - public Allocation getVertexAllocation() { - return mVertexBuffer; - } - - public Allocation getLoopAllocation() { - return mLoopBuffer; - } - - public Primitive getPrimitive() { - return mPrimitive; - } - - @Override - void updateFromNative() { - } - - - public static Path createStaticPath(RenderScript rs, Primitive p, float quality, Allocation vtx) { - long id = rs.nPathCreate(p.mID, false, vtx.getID(rs), 0, quality); - Path newPath = new Path(id, rs, p, null, null, quality); - return newPath; - } - - public static Path createStaticPath(RenderScript rs, Primitive p, float quality, Allocation vtx, Allocation loops) { - return null; - } - - public static Path createDynamicPath(RenderScript rs, Primitive p, float quality, Allocation vtx) { - return null; - } - - public static Path createDynamicPath(RenderScript rs, Primitive p, float quality, Allocation vtx, Allocation loops) { - return null; - } - - -} - - diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java index b992d44df47e..f08c9853f873 100644 --- a/rs/java/android/renderscript/RenderScript.java +++ b/rs/java/android/renderscript/RenderScript.java @@ -908,12 +908,6 @@ public class RenderScript { rsnMeshGetIndices(mContext, id, idxIds, primitives, vtxIdCount); } - native long rsnPathCreate(long con, int prim, boolean isStatic, long vtx, long loop, float q); - synchronized long nPathCreate(int prim, boolean isStatic, long vtx, long loop, float q) { - validate(); - return rsnPathCreate(mContext, prim, isStatic, vtx, loop, q); - } - native void rsnScriptIntrinsicBLAS_Single(long con, long id, int func, int TransA, int TransB, int Side, int Uplo, int Diag, int M, int N, int K, float alpha, long A, long B, float beta, long C, int incX, int incY, diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp index f2c9d3196587..6d6757dfed7d 100644 --- a/rs/jni/android_renderscript_RenderScript.cpp +++ b/rs/jni/android_renderscript_RenderScript.cpp @@ -1315,7 +1315,7 @@ nAllocationElementRead(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jbyte *ptr = _env->GetByteArrayElements(data, nullptr); rsAllocationElementRead((RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, - lod, ptr, sizeBytes, compIdx); + lod, ptr, sizeBytes, compIdx); _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT); } @@ -2184,18 +2184,6 @@ nSamplerCreate(JNIEnv *_env, jobject _this, jlong con, jint magFilter, jint minF // --------------------------------------------------------------------------- static jlong -nPathCreate(JNIEnv *_env, jobject _this, jlong con, jint prim, jboolean isStatic, jlong _vtx, jlong _loop, jfloat q) { - if (kLogApi) { - ALOGD("nPathCreate, con(%p)", (RsContext)con); - } - - jlong id = (jlong)(uintptr_t)rsPathCreate((RsContext)con, (RsPathPrimitive)prim, isStatic, - (RsAllocation)_vtx, - (RsAllocation)_loop, q); - return id; -} - -static jlong nMeshCreate(JNIEnv *_env, jobject _this, jlong con, jlongArray _vtx, jlongArray _idx, jintArray _prim) { if (kLogApi) { @@ -2444,7 +2432,6 @@ static JNINativeMethod methods[] = { {"rsnSamplerCreate", "(JIIIIIF)J", (void*)nSamplerCreate }, -{"rsnPathCreate", "(JIZJJF)J", (void*)nPathCreate }, {"rsnMeshCreate", "(J[J[J[I)J", (void*)nMeshCreate }, {"rsnMeshGetVertexBufferCount", "(JJ)I", (void*)nMeshGetVertexBufferCount }, diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index ac893e0e467c..9f22aa95fde1 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -2445,9 +2445,11 @@ final class ActivityStack { } int taskNdx = mTaskHistory.indexOf(task); - do { - taskTop = mTaskHistory.get(taskNdx--).getTopActivity(); - } while (taskTop == null && taskNdx >= 0); + if (taskNdx >= 0) { + do { + taskTop = mTaskHistory.get(taskNdx--).getTopActivity(); + } while (taskTop == null && taskNdx >= 0); + } if (topOptions != null) { // If we got some ActivityOptions from an activity on top that diff --git a/services/core/java/com/android/server/pm/InstructionSets.java b/services/core/java/com/android/server/pm/InstructionSets.java new file mode 100644 index 000000000000..79e7a20fff0f --- /dev/null +++ b/services/core/java/com/android/server/pm/InstructionSets.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.pm; + +import android.content.pm.ApplicationInfo; +import android.os.Build; +import android.os.SystemProperties; +import android.text.TextUtils; +import android.util.ArraySet; + +import java.util.ArrayList; +import java.util.List; + +import dalvik.system.VMRuntime; + +/** + * Provides various methods for obtaining and converting of instruction sets. + * + * @hide + */ +public class InstructionSets { + private static final String PREFERRED_INSTRUCTION_SET = + VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]);; + public static String[] getAppDexInstructionSets(ApplicationInfo info) { + if (info.primaryCpuAbi != null) { + if (info.secondaryCpuAbi != null) { + return new String[] { + VMRuntime.getInstructionSet(info.primaryCpuAbi), + VMRuntime.getInstructionSet(info.secondaryCpuAbi) }; + } else { + return new String[] { + VMRuntime.getInstructionSet(info.primaryCpuAbi) }; + } + } + + return new String[] { getPreferredInstructionSet() }; + } + + public static String[] getAppDexInstructionSets(PackageSetting ps) { + if (ps.primaryCpuAbiString != null) { + if (ps.secondaryCpuAbiString != null) { + return new String[] { + VMRuntime.getInstructionSet(ps.primaryCpuAbiString), + VMRuntime.getInstructionSet(ps.secondaryCpuAbiString) }; + } else { + return new String[] { + VMRuntime.getInstructionSet(ps.primaryCpuAbiString) }; + } + } + + return new String[] { getPreferredInstructionSet() }; + } + + public static String getPreferredInstructionSet() { + return PREFERRED_INSTRUCTION_SET; + } + + /** + * Returns the instruction set that should be used to compile dex code. In the presence of + * a native bridge this might be different than the one shared libraries use. + */ + public static String getDexCodeInstructionSet(String sharedLibraryIsa) { + String dexCodeIsa = SystemProperties.get("ro.dalvik.vm.isa." + sharedLibraryIsa); + return TextUtils.isEmpty(dexCodeIsa) ? sharedLibraryIsa : dexCodeIsa; + } + + public static String[] getDexCodeInstructionSets(String[] instructionSets) { + ArraySet<String> dexCodeInstructionSets = new ArraySet<String>(instructionSets.length); + for (String instructionSet : instructionSets) { + dexCodeInstructionSets.add(getDexCodeInstructionSet(instructionSet)); + } + return dexCodeInstructionSets.toArray(new String[dexCodeInstructionSets.size()]); + } + + /** + * Returns deduplicated list of supported instructions for dex code. + */ + public static String[] getAllDexCodeInstructionSets() { + String[] supportedInstructionSets = new String[Build.SUPPORTED_ABIS.length]; + for (int i = 0; i < supportedInstructionSets.length; i++) { + String abi = Build.SUPPORTED_ABIS[i]; + supportedInstructionSets[i] = VMRuntime.getInstructionSet(abi); + } + return getDexCodeInstructionSets(supportedInstructionSets); + } + + public 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; + } +} diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java new file mode 100644 index 000000000000..2dbce0a4ff52 --- /dev/null +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.pm; + +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageParser; +import android.os.UserHandle; +import android.util.ArraySet; +import android.util.Log; +import android.util.Slog; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import dalvik.system.DexFile; +import dalvik.system.StaleDexCacheError; + +import static com.android.server.pm.InstructionSets.getAppDexInstructionSets; +import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets; + +/** + * Helper class for running dexopt command on packages. + */ +final class PackageDexOptimizer { + static final String TAG = "PackageManager.DexOptimizer"; + static final int DEX_OPT_SKIPPED = 0; + static final int DEX_OPT_PERFORMED = 1; + static final int DEX_OPT_DEFERRED = 2; + static final int DEX_OPT_FAILED = -1; + + private final PackageManagerService mPackageManagerService; + private ArraySet<PackageParser.Package> mDeferredDexOpt; + + PackageDexOptimizer(PackageManagerService packageManagerService) { + this.mPackageManagerService = packageManagerService; + } + + /** + * Performs dexopt on all code paths and libraries of the specified package for specified + * instruction sets. + * + * <p>Calls to {@link com.android.server.pm.Installer#dexopt} are synchronized on + * {@link PackageManagerService#mInstallLock}. + */ + int performDexOpt(PackageParser.Package pkg, String[] instructionSets, + boolean forceDex, boolean defer, boolean inclDependencies) { + ArraySet<String> done; + if (inclDependencies && (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null)) { + done = new ArraySet<String>(); + done.add(pkg.packageName); + } else { + done = null; + } + synchronized (mPackageManagerService.mInstallLock) { + return performDexOptLI(pkg, instructionSets, forceDex, defer, done); + } + } + + private int performDexOptLI(PackageParser.Package pkg, String[] targetInstructionSets, + boolean forceDex, boolean defer, ArraySet<String> done) { + final String[] instructionSets = targetInstructionSets != null ? + targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo); + + if (done != null) { + done.add(pkg.packageName); + if (pkg.usesLibraries != null) { + performDexOptLibsLI(pkg.usesLibraries, instructionSets, forceDex, defer, done); + } + if (pkg.usesOptionalLibraries != null) { + performDexOptLibsLI(pkg.usesOptionalLibraries, instructionSets, forceDex, defer, + done); + } + } + + if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) == 0) { + return DEX_OPT_SKIPPED; + } + + final boolean vmSafeMode = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0; + final boolean debuggable = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; + + final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly(); + boolean performedDexOpt = false; + // There are three basic cases here: + // 1.) we need to dexopt, either because we are forced or it is needed + // 2.) we are deferring a needed dexopt + // 3.) we are skipping an unneeded dexopt + final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets); + for (String dexCodeInstructionSet : dexCodeInstructionSets) { + if (!forceDex && pkg.mDexOptPerformed.contains(dexCodeInstructionSet)) { + continue; + } + + for (String path : paths) { + try { + // This will return DEXOPT_NEEDED if we either cannot find any odex file for this + // package or the one we find does not match the image checksum (i.e. it was + // compiled against an old image). It will return PATCHOAT_NEEDED if we can find a + // odex file and it matches the checksum of the image but not its base address, + // meaning we need to move it. + final byte isDexOptNeeded = DexFile.isDexOptNeededInternal(path, + pkg.packageName, dexCodeInstructionSet, defer); + if (forceDex || (!defer && isDexOptNeeded == DexFile.DEXOPT_NEEDED)) { + Log.i(TAG, "Running dexopt on: " + path + " pkg=" + + pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet + + " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable); + final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); + final int ret = mPackageManagerService.mInstaller.dexopt(path, sharedGid, + !pkg.isForwardLocked(), pkg.packageName, dexCodeInstructionSet, + vmSafeMode, debuggable); + + if (ret < 0) { + // Don't bother running dexopt again if we failed, it will probably + // just result in an error again. Also, don't bother dexopting for other + // paths & ISAs. + return DEX_OPT_FAILED; + } + + performedDexOpt = true; + } else if (!defer && isDexOptNeeded == DexFile.PATCHOAT_NEEDED) { + Log.i(TAG, "Running patchoat on: " + pkg.applicationInfo.packageName); + final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); + final int ret = mPackageManagerService.mInstaller.patchoat(path, sharedGid, + !pkg.isForwardLocked(), pkg.packageName, dexCodeInstructionSet); + + if (ret < 0) { + // Don't bother running patchoat again if we failed, it will probably + // just result in an error again. Also, don't bother dexopting for other + // paths & ISAs. + return DEX_OPT_FAILED; + } + + performedDexOpt = true; + } + + // We're deciding to defer a needed dexopt. Don't bother dexopting for other + // paths and instruction sets. We'll deal with them all together when we process + // our list of deferred dexopts. + if (defer && isDexOptNeeded != DexFile.UP_TO_DATE) { + addPackageForDeferredDexopt(pkg); + return DEX_OPT_DEFERRED; + } + } catch (FileNotFoundException e) { + Slog.w(TAG, "Apk not found for dexopt: " + path); + return DEX_OPT_FAILED; + } catch (IOException e) { + Slog.w(TAG, "IOException reading apk: " + path, e); + return DEX_OPT_FAILED; + } catch (StaleDexCacheError e) { + Slog.w(TAG, "StaleDexCacheError when reading apk: " + path, e); + return DEX_OPT_FAILED; + } catch (Exception e) { + Slog.w(TAG, "Exception when doing dexopt : ", e); + return DEX_OPT_FAILED; + } + } + + // At this point we haven't failed dexopt and we haven't deferred dexopt. We must + // either have either succeeded dexopt, or have had isDexOptNeededInternal tell us + // it isn't required. We therefore mark that this package doesn't need dexopt unless + // it's forced. performedDexOpt will tell us whether we performed dex-opt or skipped + // it. + pkg.mDexOptPerformed.add(dexCodeInstructionSet); + } + + // If we've gotten here, we're sure that no error occurred and that we haven't + // deferred dex-opt. We've either dex-opted one more paths or instruction sets or + // we've skipped all of them because they are up to date. In both cases this + // package doesn't need dexopt any longer. + return performedDexOpt ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED; + } + + private void performDexOptLibsLI(ArrayList<String> libs, String[] instructionSets, + boolean forceDex, boolean defer, ArraySet<String> done) { + for (String libName : libs) { + PackageParser.Package libPkg = mPackageManagerService.findSharedNonSystemLibrary( + libName); + if (libPkg != null && !done.contains(libName)) { + performDexOptLI(libPkg, instructionSets, forceDex, defer, done); + } + } + } + + /** + * Clears set of deferred dexopt packages. + * @return content of dexopt set if it was not empty + */ + public ArraySet<PackageParser.Package> clearDeferredDexOptPackages() { + ArraySet<PackageParser.Package> result = mDeferredDexOpt; + mDeferredDexOpt = null; + return result; + } + + public void addPackageForDeferredDexopt(PackageParser.Package pkg) { + if (mDeferredDexOpt == null) { + mDeferredDexOpt = new ArraySet<PackageParser.Package>(); + } + mDeferredDexOpt.add(pkg); + } +} diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index b297887bc77d..aba930fb7abd 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -55,6 +55,10 @@ import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME; import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME; import static com.android.internal.util.ArrayUtils.appendInt; import static com.android.internal.util.ArrayUtils.removeInt; +import static com.android.server.pm.InstructionSets.getAppDexInstructionSets; +import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet; +import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets; +import static com.android.server.pm.InstructionSets.getPreferredInstructionSet; import android.util.ArrayMap; @@ -184,7 +188,6 @@ import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileDescriptor; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; @@ -213,7 +216,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import dalvik.system.DexFile; -import dalvik.system.StaleDexCacheError; import dalvik.system.VMRuntime; import libcore.io.IoUtils; @@ -323,13 +325,8 @@ public class PackageManagerService extends IPackageManager.Stub { private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay"; - private static String sPreferredInstructionSet; - final ServiceThread mHandlerThread; - private static final String IDMAP_PREFIX = "/data/resource-cache/"; - private static final String IDMAP_SUFFIX = "@idmap"; - final PackageHandler mHandler; /** @@ -466,8 +463,7 @@ public class PackageManagerService extends IPackageManager.Stub { final PackageInstallerService mInstallerService; - ArraySet<PackageParser.Package> mDeferredDexOpt = null; - + private final PackageDexOptimizer mPackageDexOptimizer; // Cache of users who need badging. SparseBooleanArray mUserNeedsBadging = new SparseBooleanArray(); @@ -1050,7 +1046,7 @@ public class PackageManagerService extends IPackageManager.Stub { res.pkg.applicationInfo.packageName, null, updateUsers); // treat asec-hosted packages like removable media on upgrade - if (isForwardLocked(res.pkg) || isExternal(res.pkg)) { + if (res.pkg.isForwardLocked() || isExternal(res.pkg)) { if (DEBUG_INSTALL) { Slog.i(TAG, "upgrading pkg " + res.pkg + " is ASEC-hosted -> AVAILABLE"); @@ -1338,6 +1334,7 @@ public class PackageManagerService extends IPackageManager.Stub { } mInstaller = installer; + mPackageDexOptimizer = new PackageDexOptimizer(this); getDefaultDisplayMetrics(context, mMetrics); @@ -1438,9 +1435,10 @@ public class PackageManagerService extends IPackageManager.Stub { Slog.w(TAG, "No SYSTEMSERVERCLASSPATH found!"); } - final List<String> allInstructionSets = getAllInstructionSets(); + final List<String> allInstructionSets = InstructionSets.getAllInstructionSets(); final String[] dexCodeInstructionSets = - getDexCodeInstructionSets(allInstructionSets.toArray(new String[allInstructionSets.size()])); + getDexCodeInstructionSets( + allInstructionSets.toArray(new String[allInstructionSets.size()])); /** * Ensure all external libraries have had dexopt run on them. @@ -2335,6 +2333,19 @@ public class PackageManagerService extends IPackageManager.Stub { return null; } + /** + * @hide + */ + PackageParser.Package findSharedNonSystemLibrary(String libName) { + synchronized (mPackages) { + PackageManagerService.SharedLibraryEntry lib = mSharedLibraries.get(libName); + if (lib != null && lib.apk != null) { + return mPackages.get(lib.apk); + } + } + return null; + } + @Override public FeatureInfo[] getSystemAvailableFeatures() { Collection<FeatureInfo> featSet; @@ -4595,8 +4606,7 @@ public class PackageManagerService extends IPackageManager.Stub { final ArraySet<PackageParser.Package> pkgs; synchronized (mPackages) { - pkgs = mDeferredDexOpt; - mDeferredDexOpt = null; + pkgs = mPackageDexOptimizer.clearDeferredDexOptPackages(); } if (pkgs != null) { @@ -4752,8 +4762,8 @@ public class PackageManagerService extends IPackageManager.Stub { } PackageParser.Package p = pkg; synchronized (mInstallLock) { - performDexOptLI(p, null /* instruction sets */, false /* force dex */, - false /* defer */, true /* include dependencies */); + mPackageDexOptimizer.performDexOpt(p, null /* instruction sets */, + false /* force dex */, false /* defer */, true /* include dependencies */); } } @@ -4802,8 +4812,9 @@ public class PackageManagerService extends IPackageManager.Stub { synchronized (mInstallLock) { final String[] instructionSets = new String[] { targetInstructionSet }; - return performDexOptLI(p, instructionSets, false /* force dex */, false /* defer */, - true /* include dependencies */) == DEX_OPT_PERFORMED; + int result = mPackageDexOptimizer.performDexOpt(p, instructionSets, + false /* forceDex */, false /* defer */, true /* inclDependencies */); + return result == PackageDexOptimizer.DEX_OPT_PERFORMED; } } @@ -4830,227 +4841,6 @@ public class PackageManagerService extends IPackageManager.Stub { mPackageUsage.write(true); } - private void performDexOptLibsLI(ArrayList<String> libs, String[] instructionSets, - boolean forceDex, boolean defer, ArraySet<String> done) { - for (int i=0; i<libs.size(); i++) { - PackageParser.Package libPkg; - String libName; - synchronized (mPackages) { - libName = libs.get(i); - SharedLibraryEntry lib = mSharedLibraries.get(libName); - if (lib != null && lib.apk != null) { - libPkg = mPackages.get(lib.apk); - } else { - libPkg = null; - } - } - if (libPkg != null && !done.contains(libName)) { - performDexOptLI(libPkg, instructionSets, forceDex, defer, done); - } - } - } - - static final int DEX_OPT_SKIPPED = 0; - static final int DEX_OPT_PERFORMED = 1; - static final int DEX_OPT_DEFERRED = 2; - static final int DEX_OPT_FAILED = -1; - - private int performDexOptLI(PackageParser.Package pkg, String[] targetInstructionSets, - boolean forceDex, boolean defer, ArraySet<String> done) { - final String[] instructionSets = targetInstructionSets != null ? - targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo); - - if (done != null) { - done.add(pkg.packageName); - if (pkg.usesLibraries != null) { - performDexOptLibsLI(pkg.usesLibraries, instructionSets, forceDex, defer, done); - } - if (pkg.usesOptionalLibraries != null) { - performDexOptLibsLI(pkg.usesOptionalLibraries, instructionSets, forceDex, defer, done); - } - } - - if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) == 0) { - return DEX_OPT_SKIPPED; - } - - final boolean vmSafeMode = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0; - final boolean debuggable = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; - - final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly(); - boolean performedDexOpt = false; - // There are three basic cases here: - // 1.) we need to dexopt, either because we are forced or it is needed - // 2.) we are defering a needed dexopt - // 3.) we are skipping an unneeded dexopt - final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets); - for (String dexCodeInstructionSet : dexCodeInstructionSets) { - if (!forceDex && pkg.mDexOptPerformed.contains(dexCodeInstructionSet)) { - continue; - } - - for (String path : paths) { - try { - // This will return DEXOPT_NEEDED if we either cannot find any odex file for this - // patckage or the one we find does not match the image checksum (i.e. it was - // compiled against an old image). It will return PATCHOAT_NEEDED if we can find a - // odex file and it matches the checksum of the image but not its base address, - // meaning we need to move it. - final byte isDexOptNeeded = DexFile.isDexOptNeededInternal(path, - pkg.packageName, dexCodeInstructionSet, defer); - if (forceDex || (!defer && isDexOptNeeded == DexFile.DEXOPT_NEEDED)) { - Log.i(TAG, "Running dexopt on: " + path + " pkg=" - + pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet - + " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable); - final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); - final int ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg), - pkg.packageName, dexCodeInstructionSet, vmSafeMode, debuggable); - - if (ret < 0) { - // Don't bother running dexopt again if we failed, it will probably - // just result in an error again. Also, don't bother dexopting for other - // paths & ISAs. - return DEX_OPT_FAILED; - } - - performedDexOpt = true; - } else if (!defer && isDexOptNeeded == DexFile.PATCHOAT_NEEDED) { - Log.i(TAG, "Running patchoat on: " + pkg.applicationInfo.packageName); - final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); - final int ret = mInstaller.patchoat(path, sharedGid, !isForwardLocked(pkg), - pkg.packageName, dexCodeInstructionSet); - - if (ret < 0) { - // Don't bother running patchoat again if we failed, it will probably - // just result in an error again. Also, don't bother dexopting for other - // paths & ISAs. - return DEX_OPT_FAILED; - } - - performedDexOpt = true; - } - - // We're deciding to defer a needed dexopt. Don't bother dexopting for other - // paths and instruction sets. We'll deal with them all together when we process - // our list of deferred dexopts. - if (defer && isDexOptNeeded != DexFile.UP_TO_DATE) { - if (mDeferredDexOpt == null) { - mDeferredDexOpt = new ArraySet<PackageParser.Package>(); - } - mDeferredDexOpt.add(pkg); - return DEX_OPT_DEFERRED; - } - } catch (FileNotFoundException e) { - Slog.w(TAG, "Apk not found for dexopt: " + path); - return DEX_OPT_FAILED; - } catch (IOException e) { - Slog.w(TAG, "IOException reading apk: " + path, e); - return DEX_OPT_FAILED; - } catch (StaleDexCacheError e) { - Slog.w(TAG, "StaleDexCacheError when reading apk: " + path, e); - return DEX_OPT_FAILED; - } catch (Exception e) { - Slog.w(TAG, "Exception when doing dexopt : ", e); - return DEX_OPT_FAILED; - } - } - - // At this point we haven't failed dexopt and we haven't deferred dexopt. We must - // either have either succeeded dexopt, or have had isDexOptNeededInternal tell us - // it isn't required. We therefore mark that this package doesn't need dexopt unless - // it's forced. performedDexOpt will tell us whether we performed dex-opt or skipped - // it. - pkg.mDexOptPerformed.add(dexCodeInstructionSet); - } - - // If we've gotten here, we're sure that no error occurred and that we haven't - // deferred dex-opt. We've either dex-opted one more paths or instruction sets or - // we've skipped all of them because they are up to date. In both cases this - // package doesn't need dexopt any longer. - return performedDexOpt ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED; - } - - private static String[] getAppDexInstructionSets(ApplicationInfo info) { - if (info.primaryCpuAbi != null) { - if (info.secondaryCpuAbi != null) { - return new String[] { - VMRuntime.getInstructionSet(info.primaryCpuAbi), - VMRuntime.getInstructionSet(info.secondaryCpuAbi) }; - } else { - return new String[] { - VMRuntime.getInstructionSet(info.primaryCpuAbi) }; - } - } - - return new String[] { getPreferredInstructionSet() }; - } - - private static String[] getAppDexInstructionSets(PackageSetting ps) { - if (ps.primaryCpuAbiString != null) { - if (ps.secondaryCpuAbiString != null) { - return new String[] { - VMRuntime.getInstructionSet(ps.primaryCpuAbiString), - VMRuntime.getInstructionSet(ps.secondaryCpuAbiString) }; - } else { - return new String[] { - VMRuntime.getInstructionSet(ps.primaryCpuAbiString) }; - } - } - - return new String[] { getPreferredInstructionSet() }; - } - - 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; - } - - /** - * Returns the instruction set that should be used to compile dex code. In the presence of - * a native bridge this might be different than the one shared libraries use. - */ - private static String getDexCodeInstructionSet(String sharedLibraryIsa) { - String dexCodeIsa = SystemProperties.get("ro.dalvik.vm.isa." + sharedLibraryIsa); - return (dexCodeIsa.isEmpty() ? sharedLibraryIsa : dexCodeIsa); - } - - private static String[] getDexCodeInstructionSets(String[] instructionSets) { - ArraySet<String> dexCodeInstructionSets = new ArraySet<String>(instructionSets.length); - for (String instructionSet : instructionSets) { - dexCodeInstructionSets.add(getDexCodeInstructionSet(instructionSet)); - } - return dexCodeInstructionSets.toArray(new String[dexCodeInstructionSets.size()]); - } - - /** - * Returns deduplicated list of supported instructions for dex code. - */ - public static String[] getAllDexCodeInstructionSets() { - String[] supportedInstructionSets = new String[Build.SUPPORTED_ABIS.length]; - for (int i = 0; i < supportedInstructionSets.length; i++) { - String abi = Build.SUPPORTED_ABIS[i]; - supportedInstructionSets[i] = VMRuntime.getInstructionSet(abi); - } - return getDexCodeInstructionSets(supportedInstructionSets); - } - @Override public void forceDexOpt(String packageName) { enforceSystemOrRoot("forceDexOpt"); @@ -5066,25 +4856,14 @@ public class PackageManagerService extends IPackageManager.Stub { synchronized (mInstallLock) { final String[] instructionSets = new String[] { getPrimaryInstructionSet(pkg.applicationInfo) }; - final int res = performDexOptLI(pkg, instructionSets, true, false, true); - if (res != DEX_OPT_PERFORMED) { + final int res = mPackageDexOptimizer.performDexOpt(pkg, instructionSets, + true /*forceDex*/, false /* defer */, true /* inclDependencies */); + if (res != PackageDexOptimizer.DEX_OPT_PERFORMED) { throw new IllegalStateException("Failed to dexopt: " + res); } } } - private int performDexOptLI(PackageParser.Package pkg, String[] instructionSets, - boolean forceDex, boolean defer, boolean inclDependencies) { - ArraySet<String> done; - if (inclDependencies && (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null)) { - done = new ArraySet<String>(); - done.add(pkg.packageName); - } else { - done = null; - } - return performDexOptLI(pkg, instructionSets, forceDex, defer, done); - } - private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) { if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) { Slog.w(TAG, "Unable to update from " + oldPkg.name @@ -5100,10 +4879,6 @@ public class PackageManagerService extends IPackageManager.Stub { return true; } - File getDataPathForUser(int userId) { - return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId); - } - private File getDataPathForPackage(String packageName, int userId) { /* * Until we fully support multiple users, return the directory we @@ -5771,7 +5546,7 @@ public class PackageManagerService extends IPackageManager.Stub { // pass once we've determined ABI below. setNativeLibraryPaths(pkg); - final boolean isAsec = isForwardLocked(pkg) || isExternal(pkg); + final boolean isAsec = pkg.isForwardLocked() || isExternal(pkg); final String nativeLibraryRootStr = pkg.applicationInfo.nativeLibraryRootDir; final boolean useIsaSpecificSubdirs = pkg.applicationInfo.nativeLibraryRootRequiresIsa; @@ -5947,8 +5722,9 @@ public class PackageManagerService extends IPackageManager.Stub { } if ((scanFlags & SCAN_NO_DEX) == 0) { - if (performDexOptLI(pkg, null /* instruction sets */, forceDex, - (scanFlags & SCAN_DEFER_DEX) != 0, false) == DEX_OPT_FAILED) { + int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instruction sets */, + forceDex, (scanFlags & SCAN_DEFER_DEX) != 0, false /* inclDependencies */); + if (result == PackageDexOptimizer.DEX_OPT_FAILED) { throw new PackageManagerException(INSTALL_FAILED_DEXOPT, "scanPackageLI"); } } @@ -6022,8 +5798,10 @@ public class PackageManagerService extends IPackageManager.Stub { if ((scanFlags & SCAN_NO_DEX) == 0) { for (int i = 0; i < clientLibPkgs.size(); i++) { PackageParser.Package clientPkg = clientLibPkgs.get(i); - if (performDexOptLI(clientPkg, null /* instruction sets */, forceDex, - (scanFlags & SCAN_DEFER_DEX) != 0, false) == DEX_OPT_FAILED) { + int result = mPackageDexOptimizer.performDexOpt(clientPkg, + null /* instruction sets */, forceDex, + (scanFlags & SCAN_DEFER_DEX) != 0, false); + if (result == PackageDexOptimizer.DEX_OPT_FAILED) { throw new PackageManagerException(INSTALL_FAILED_DEXOPT, "scanPackageLI failed to dexopt clientLibPkgs"); } @@ -6492,14 +6270,15 @@ public class PackageManagerService extends IPackageManager.Stub { ps.pkg.applicationInfo.primaryCpuAbi = adjustedAbi; Slog.i(TAG, "Adjusting ABI for : " + ps.name + " to " + adjustedAbi); - if (performDexOptLI(ps.pkg, null /* instruction sets */, forceDexOpt, - deferDexOpt, true) == DEX_OPT_FAILED) { + int result = mPackageDexOptimizer.performDexOpt(ps.pkg, + null /* instruction sets */, forceDexOpt, deferDexOpt, true); + if (result == PackageDexOptimizer.DEX_OPT_FAILED) { ps.primaryCpuAbiString = null; ps.pkg.applicationInfo.primaryCpuAbi = null; return; } else { mInstaller.rmdex(ps.codePathString, - getDexCodeInstructionSet(getPreferredInstructionSet())); + getDexCodeInstructionSet(getPreferredInstructionSet())); } } } @@ -6572,7 +6351,7 @@ public class PackageManagerService extends IPackageManager.Stub { final String codePath = pkg.codePath; final File codeFile = new File(codePath); final boolean bundledApp = isSystemApp(info) && !isUpdatedSystemApp(info); - final boolean asecApp = isForwardLocked(info) || isExternal(info); + final boolean asecApp = info.isForwardLocked() || isExternal(info); info.nativeLibraryRootDir = null; info.nativeLibraryRootRequiresIsa = false; @@ -9407,6 +9186,25 @@ public class PackageManagerService extends IPackageManager.Stub { } } + private void removeDexFiles(List<String> allCodePaths, String[] instructionSets) { + if (!allCodePaths.isEmpty()) { + if (instructionSets == null) { + throw new IllegalStateException("instructionSet == null"); + } + String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets); + for (String codePath : allCodePaths) { + for (String dexCodeInstructionSet : dexCodeInstructionSets) { + int retCode = mInstaller.rmdex(codePath, dexCodeInstructionSet); + if (retCode < 0) { + Slog.w(TAG, "Couldn't remove dex file for package: " + + " at location " + codePath + ", retcode=" + retCode); + // we don't consider this to be a failure of the core package deletion + } + } + } + } + } + /** * Logic to handle installation of non-ASEC applications, including copying * and renaming logic. @@ -9619,23 +9417,7 @@ public class PackageManagerService extends IPackageManager.Stub { } cleanUp(); - - if (!allCodePaths.isEmpty()) { - if (instructionSets == null) { - throw new IllegalStateException("instructionSet == null"); - } - String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets); - for (String codePath : allCodePaths) { - for (String dexCodeInstructionSet : dexCodeInstructionSets) { - int retCode = mInstaller.rmdex(codePath, dexCodeInstructionSet); - if (retCode < 0) { - Slog.w(TAG, "Couldn't remove dex file for package: " - + " at location " + codePath + ", retcode=" + retCode); - // we don't consider this to be a failure of the core package deletion - } - } - } - } + removeDexFiles(allCodePaths, instructionSets); } boolean doPostDeleteLI(boolean delete) { @@ -9940,31 +9722,10 @@ public class PackageManagerService extends IPackageManager.Stub { private void cleanUpResourcesLI(List<String> allCodePaths) { cleanUp(); - - if (!allCodePaths.isEmpty()) { - if (instructionSets == null) { - throw new IllegalStateException("instructionSet == null"); - } - String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets); - for (String codePath : allCodePaths) { - for (String dexCodeInstructionSet : dexCodeInstructionSets) { - int retCode = mInstaller.rmdex(codePath, dexCodeInstructionSet); - if (retCode < 0) { - Slog.w(TAG, "Couldn't remove dex file for package: " - + " at location " + codePath + ", retcode=" + retCode); - // we don't consider this to be a failure of the core package deletion - } - } - } - } + removeDexFiles(allCodePaths, instructionSets); } - boolean matchContainer(String app) { - if (cid.startsWith(app)) { - return true; - } - return false; - } + String getPackageName() { return getAsecPackageName(cid); @@ -10282,7 +10043,7 @@ public class PackageManagerService extends IPackageManager.Stub { // If deleted package lived in a container, give users a chance to // relinquish resources before killing. - if (isForwardLocked(deletedPackage) || isExternal(deletedPackage)) { + if (deletedPackage.isForwardLocked() || isExternal(deletedPackage)) { if (DEBUG_INSTALL) { Slog.i(TAG, "upgrading pkg " + deletedPackage + " is ASEC-hosted -> UNAVAILABLE"); } @@ -10323,7 +10084,7 @@ public class PackageManagerService extends IPackageManager.Stub { // Parse old package boolean oldOnSd = isExternal(deletedPackage); int oldParseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY | - (isForwardLocked(deletedPackage) ? PackageParser.PARSE_FORWARD_LOCK : 0) | + (deletedPackage.isForwardLocked() ? PackageParser.PARSE_FORWARD_LOCK : 0) | (oldOnSd ? PackageParser.PARSE_ON_SDCARD : 0); int oldScanFlags = SCAN_UPDATE_SIGNATURE | SCAN_UPDATE_TIME; try { @@ -10713,18 +10474,6 @@ public class PackageManagerService extends IPackageManager.Stub { } } - private static boolean isForwardLocked(PackageParser.Package pkg) { - return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0; - } - - private static boolean isForwardLocked(ApplicationInfo info) { - return (info.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0; - } - - private boolean isForwardLocked(PackageSetting ps) { - return (ps.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0; - } - private static boolean isMultiArch(PackageSetting ps) { return (ps.pkgFlags & ApplicationInfo.FLAG_MULTIARCH) != 0; } @@ -10778,7 +10527,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (isExternal(ps)) { installFlags |= PackageManager.INSTALL_EXTERNAL; } - if (isForwardLocked(ps)) { + if (ps.isForwardLocked()) { installFlags |= PackageManager.INSTALL_FORWARD_LOCK; } return installFlags; @@ -11632,7 +11381,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (ps != null) { libDirRoot = ps.legacyNativeLibraryPathString; } - if (p != null && (isExternal(p) || isForwardLocked(p))) { + if (p != null && (isExternal(p) || p.isForwardLocked())) { String secureContainerId = cidFromCodePath(p.applicationInfo.getBaseCodePath()); if (secureContainerId != null) { asecPath = PackageHelper.getSdFilesystem(secureContainerId); @@ -11646,7 +11395,7 @@ public class PackageManagerService extends IPackageManager.Stub { Slog.w(TAG, "Package " + packageName + " has no applicationInfo."); return false; } - if (isForwardLocked(p)) { + if (p.isForwardLocked()) { publicSrcDir = applicationInfo.getBaseResourcePath(); } } @@ -12986,7 +12735,7 @@ public class PackageManagerService extends IPackageManager.Stub { } final AsecInstallArgs args = new AsecInstallArgs(cid, - getAppDexInstructionSets(ps), isForwardLocked(ps)); + getAppDexInstructionSets(ps), ps.isForwardLocked()); // The package status is changed only if the code path // matches between settings and the container id. if (ps.codePathString != null @@ -13268,7 +13017,7 @@ public class PackageManagerService extends IPackageManager.Stub { Slog.w(TAG, "No move required. Trying to move to same location"); returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION; } else { - if (isForwardLocked(pkg)) { + if (pkg.isForwardLocked()) { currInstallFlags |= PackageManager.INSTALL_FORWARD_LOCK; newInstallFlags |= PackageManager.INSTALL_FORWARD_LOCK; } diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index 8ea0bee4bd6e..06d842a1f0b9 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -64,4 +64,8 @@ final class PackageSetting extends PackageSettingBase { public boolean isPrivileged() { return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; } + + public boolean isForwardLocked() { + return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0; + } } diff --git a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java index 111c09b1570c..de9360e41006 100644 --- a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java +++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java @@ -18,6 +18,7 @@ package com.android.server.storage; import com.android.server.EventLogTags; import com.android.server.SystemService; +import com.android.server.pm.InstructionSets; import com.android.server.pm.PackageManagerService; import android.app.Notification; @@ -341,7 +342,7 @@ public class DeviceStorageMonitorService extends SystemService { } private static boolean isBootImageOnDisk() { - for (String instructionSet : PackageManagerService.getAllDexCodeInstructionSets()) { + for (String instructionSet : InstructionSets.getAllDexCodeInstructionSets()) { if (!VMRuntime.isBootClassPathOnDisk(instructionSet)) { return false; } |