diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index c507245059272..0d463ee6d3ec4 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -690,6 +690,17 @@ public abstract class PackageManager { */ public static final int DELETE_ALL_USERS = 0x00000002; + /** + * Flag parameter for {@link #deletePackage} to indicate that, if you are calling + * uninstall on a system that has been updated, then don't do the normal process + * of uninstalling the update and rolling back to the older system version (which + * needs to happen for all users); instead, just mark the app as uninstalled for + * the current user. + * + * @hide + */ + public static final int DELETE_SYSTEM_APP = 0x00000004; + /** * Return code for when package deletion succeeds. This is passed to the * {@link IPackageDeleteObserver} by {@link #deletePackage()} if the system diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index e1887bc644525..5eac90373d173 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -1941,6 +1941,28 @@ public class PackageParser { return false; } + } else if (tagName.equals("library")) { + sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestLibrary); + + // Note: don't allow this value to be a reference to a resource + // that may change. + String lname = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestLibrary_name); + + sa.recycle(); + + if (lname != null) { + if (owner.libraryNames == null) { + owner.libraryNames = new ArrayList(); + } + if (!owner.libraryNames.contains(lname)) { + owner.libraryNames.add(lname.intern()); + } + } + + XmlUtils.skipCurrentTag(parser); + } else if (tagName.equals("uses-library")) { sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestUsesLibrary); @@ -3182,7 +3204,8 @@ public class PackageParser { public final ArrayList requestedPermissionsRequired = new ArrayList(); public ArrayList protectedBroadcasts; - + + public ArrayList libraryNames = null; public ArrayList usesLibraries = null; public ArrayList usesOptionalLibraries = null; public String[] usesLibraryFiles = null; diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index d899e9dc61b6d..f1d8c03c5e58d 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -1065,6 +1065,21 @@ + + + + + + + + + + + + + + + + + + + diff --git a/tests/SharedLibrary/client/res/values/strings.xml b/tests/SharedLibrary/client/res/values/strings.xml new file mode 100644 index 0000000000000..3757a2554f8b2 --- /dev/null +++ b/tests/SharedLibrary/client/res/values/strings.xml @@ -0,0 +1,19 @@ + + + + + SharedLibrary client + diff --git a/tests/SharedLibrary/client/src/com/google/android/test/lib_client/ActivityMain.java b/tests/SharedLibrary/client/src/com/google/android/test/lib_client/ActivityMain.java new file mode 100644 index 0000000000000..d6121a503780b --- /dev/null +++ b/tests/SharedLibrary/client/src/com/google/android/test/lib_client/ActivityMain.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.test.lib_client; + +import android.app.Activity; +import android.os.Bundle; +import android.widget.TextView; +import com.google.android.test.shared_library.SharedLibraryMain; + +public class ActivityMain extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + TextView content = new TextView(this); + content.setText("Library version: " + SharedLibraryMain.getVersion(this) + "!"); + + SharedLibraryMain.ensureVersion(this, SharedLibraryMain.VERSION_BASE); + setContentView(content); + } +} diff --git a/tests/SharedLibrary/lib/Android.mk b/tests/SharedLibrary/lib/Android.mk new file mode 100644 index 0000000000000..c19e23adcbeef --- /dev/null +++ b/tests/SharedLibrary/lib/Android.mk @@ -0,0 +1,10 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_PACKAGE_NAME := SharedLibrary + +LOCAL_MODULE_TAGS := tests + +include $(BUILD_PACKAGE) diff --git a/tests/SharedLibrary/lib/AndroidManifest.xml b/tests/SharedLibrary/lib/AndroidManifest.xml new file mode 100644 index 0000000000000..31fac20e41636 --- /dev/null +++ b/tests/SharedLibrary/lib/AndroidManifest.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/tests/SharedLibrary/lib/res/values/strings.xml b/tests/SharedLibrary/lib/res/values/strings.xml new file mode 100644 index 0000000000000..bbfb0b4d81d5f --- /dev/null +++ b/tests/SharedLibrary/lib/res/values/strings.xml @@ -0,0 +1,22 @@ + + + + + Upgrade required + %1$s requires a newer version + of %2$s to run. + Upgrade + diff --git a/tests/SharedLibrary/lib/src/com/google/android/test/shared_library/ActivityMain.java b/tests/SharedLibrary/lib/src/com/google/android/test/shared_library/ActivityMain.java new file mode 100644 index 0000000000000..895acedb1e7f3 --- /dev/null +++ b/tests/SharedLibrary/lib/src/com/google/android/test/shared_library/ActivityMain.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.test.shared_library; + +import android.app.Activity; +import android.os.Bundle; +import android.widget.TextView; + +public class ActivityMain extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + TextView content = new TextView(this); + content.setText("Dummy main entry for this apk; not really needed..."); + setContentView(content); + } +} diff --git a/tests/SharedLibrary/lib/src/com/google/android/test/shared_library/SharedLibraryMain.java b/tests/SharedLibrary/lib/src/com/google/android/test/shared_library/SharedLibraryMain.java new file mode 100644 index 0000000000000..c1cd9254a30d2 --- /dev/null +++ b/tests/SharedLibrary/lib/src/com/google/android/test/shared_library/SharedLibraryMain.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.test.shared_library; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.res.Resources; + +public class SharedLibraryMain { + private static String LIBRARY_PACKAGE = "com.google.android.test.shared_library"; + + /** + * Base version of the library. + */ + public static int VERSION_BASE = 1; + + /** + * The second version of the library. + */ + public static int VERSION_SECOND = 2; + + public static int getVersion(Context context) { + PackageInfo pi = null; + try { + pi = context.getPackageManager().getPackageInfo(LIBRARY_PACKAGE, 0); + return pi.versionCode; + } catch (PackageManager.NameNotFoundException e) { + throw new IllegalStateException("Can't find my package!", e); + } + } + + public static void ensureVersion(Activity activity, int minVersion) { + if (getVersion(activity) >= minVersion) { + return; + } + + // The current version of the library does not meet the required version. Show + // a dialog to inform the user and have them update to the current version. + // Note that updating the library will be necessity mean killing the current + // application (so it can be re-started with the new version, so there is no + // reason to return a result here. + final Context context; + try { + context = activity.createPackageContext(LIBRARY_PACKAGE, 0); + } catch (PackageManager.NameNotFoundException e) { + throw new IllegalStateException("Can't find my package!", e); + } + + // Display the dialog. Note that we don't need to deal with activity lifecycle + // stuff because if the activity gets recreated, it will first call through to + // ensureVersion(), causing us to either re-display the dialog if needed or let + // it now proceed. + final Resources res = context.getResources(); + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setTitle(res.getText(R.string.upgrade_title)); + builder.setMessage(res.getString(R.string.upgrade_body, + activity.getApplicationInfo().loadLabel(activity.getPackageManager()), + context.getApplicationInfo().loadLabel(context.getPackageManager()))); + builder.setPositiveButton(res.getText(R.string.upgrade_button), + new Dialog.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // Launch play store. + } + }); + builder.show(); + } +}