android\frameworks\base\core\java\com\android\internal\content\PackageMonitor.javapackagecom.android.internal.content;importandroid.app.Activity;importandroid.content.Context;importandroid.content.Intent;importandroid.content.IntentFilter;importandroid.net.Uri;importandroid.os.Handler;importandroid.os.HandlerThread;importandroid.os.Looper;importandroid.os.UserHandle;importcom.android.internal.os.BackgroundThread;importjava.util.HashSet;/*** Helper class for monitoring the state of packages: adding, removing,
* updating, and disappearing and reappearing on the SD card.*/
public abstract class PackageMonitor extendsandroid.content.BroadcastReceiver {static final IntentFilter sPackageFilt = newIntentFilter();static final IntentFilter sNonDataFilt = newIntentFilter();static final IntentFilter sExternalFilt = newIntentFilter();static{
sPackageFilt.addAction(Intent.ACTION_PACKAGE_ADDED);
sPackageFilt.addAction(Intent.ACTION_PACKAGE_REMOVED);
sPackageFilt.addAction(Intent.ACTION_PACKAGE_CHANGED);
sPackageFilt.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
sPackageFilt.addAction(Intent.ACTION_PACKAGE_RESTARTED);
sPackageFilt.addAction(Intent.ACTION_UID_REMOVED);
sPackageFilt.addDataScheme("package");
sNonDataFilt.addAction(Intent.ACTION_UID_REMOVED);
sNonDataFilt.addAction(Intent.ACTION_USER_STOPPED);
sExternalFilt.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
sExternalFilt.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
}final HashSet mUpdatingPackages = new HashSet();
Context mRegisteredContext;
Handler mRegisteredHandler;
String[] mDisappearingPackages;
String[] mAppearingPackages;
String[] mModifiedPackages;intmChangeType;int mChangeUserId =UserHandle.USER_NULL;booleanmSomePackagesChanged;
String[] mTempArray= new String[1];public void register(Context context, Looper thread, booleanexternalStorage) {
register(context, thread,null, externalStorage);
}public voidregister(Context context, Looper thread, UserHandle user,booleanexternalStorage) {if (mRegisteredContext != null) {throw new IllegalStateException("Already registered");
}
mRegisteredContext=context;if (thread == null) {
mRegisteredHandler=BackgroundThread.getHandler();
}else{
mRegisteredHandler= newHandler(thread);
}if (user != null) {
context.registerReceiverAsUser(this, user, sPackageFilt, null, mRegisteredHandler);
context.registerReceiverAsUser(this, user, sNonDataFilt, null, mRegisteredHandler);if(externalStorage) {
context.registerReceiverAsUser(this, user, sExternalFilt, null,
mRegisteredHandler);
}
}else{
context.registerReceiver(this, sPackageFilt, null, mRegisteredHandler);
context.registerReceiver(this, sNonDataFilt, null, mRegisteredHandler);if(externalStorage) {
context.registerReceiver(this, sExternalFilt, null, mRegisteredHandler);
}
}
}publicHandler getRegisteredHandler() {returnmRegisteredHandler;
}public voidunregister() {if (mRegisteredContext == null) {throw new IllegalStateException("Not registered");
}
mRegisteredContext.unregisterReceiver(this);
mRegisteredContext= null;
}//not yet implemented
booleanisPackageUpdating(String packageName) {synchronized(mUpdatingPackages) {returnmUpdatingPackages.contains(packageName);
}
}public voidonBeginPackageChanges() {
}/*** Called when a package is really added (and not replaced).*/
public void onPackageAdded(String packageName, intuid) {
}/*** Called when a package is really removed (and not replaced).*/
public void onPackageRemoved(String packageName, intuid) {
}/*** Called when a package is really removed (and not replaced) for
* all users on the device.*/
public void onPackageRemovedAllUsers(String packageName, intuid) {
}public void onPackageUpdateStarted(String packageName, intuid) {
}public void onPackageUpdateFinished(String packageName, intuid) {
}/*** Direct reflection of {@linkIntent#ACTION_PACKAGE_CHANGED
* Intent.ACTION_PACKAGE_CHANGED} being received, informing you of
* changes to the enabled/disabled state of components in a package
* and/or of the overall package.
*
*@parampackageName The name of the package that is changing.
*@paramuid The user ID the package runs under.
*@paramcomponents Any components in the package that are changing. If
* the overall package is changing, this will contain an entry of the
* package name itself.
*@returnReturn true to indicate you care about this change, which will
* result in {@link#onSomePackagesChanged()} being called later. If you
* return false, no further callbacks will happen about this change. The
* default implementation returns true if this is a change to the entire
* package.*/
public boolean onPackageChanged(String packageName, intuid, String[] components) {if (components != null) {for(String name : components) {if(packageName.equals(name)) {return true;
}
}
}return false;
}public boolean onHandleForceStop(Intent intent, String[] packages, int uid, booleandoit) {return false;
}public void onHandleUserStop(Intent intent, intuserHandle) {
}public void onUidRemoved(intuid) {
}public voidonPackagesAvailable(String[] packages) {
}public voidonPackagesUnavailable(String[] packages) {
}public static final int PACKAGE_UNCHANGED = 0;public static final int PACKAGE_UPDATING = 1;public static final int PACKAGE_TEMPORARY_CHANGE = 2;public static final int PACKAGE_PERMANENT_CHANGE = 3;/*** Called when a package disappears for any reason.*/
public void onPackageDisappeared(String packageName, intreason) {
}/*** Called when a package appears for any reason.*/
public void onPackageAppeared(String packageName, intreason) {
}/*** Called when an existing package is updated or its disabled state changes.*/
public voidonPackageModified(String packageName) {
}public booleandidSomePackagesChange() {returnmSomePackagesChanged;
}public intisPackageAppearing(String packageName) {if (mAppearingPackages != null) {for (int i=mAppearingPackages.length-1; i>=0; i--) {if(packageName.equals(mAppearingPackages[i])) {returnmChangeType;
}
}
}returnPACKAGE_UNCHANGED;
}public booleananyPackagesAppearing() {return mAppearingPackages != null;
}public intisPackageDisappearing(String packageName) {if (mDisappearingPackages != null) {for (int i=mDisappearingPackages.length-1; i>=0; i--) {if(packageName.equals(mDisappearingPackages[i])) {returnmChangeType;
}
}
}returnPACKAGE_UNCHANGED;
}public booleananyPackagesDisappearing() {return mDisappearingPackages != null;
}public booleanisPackageModified(String packageName) {if (mModifiedPackages != null) {for (int i=mModifiedPackages.length-1; i>=0; i--) {if(packageName.equals(mModifiedPackages[i])) {return true;
}
}
}return false;
}public voidonSomePackagesChanged() {
}public voidonFinishPackageChanges() {
}public intgetChangingUserId() {returnmChangeUserId;
}
String getPackageName(Intent intent) {
Uri uri=intent.getData();
String pkg= uri != null ? uri.getSchemeSpecificPart() : null;returnpkg;
}
@Overridepublic voidonReceive(Context context, Intent intent) {
mChangeUserId=intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
UserHandle.USER_NULL);if (mChangeUserId ==UserHandle.USER_NULL) {throw newIllegalArgumentException("Intent broadcast does not contain user handle: " +intent);
}
onBeginPackageChanges();
mDisappearingPackages= mAppearingPackages = null;
mSomePackagesChanged= false;
String action=intent.getAction();if(Intent.ACTION_PACKAGE_ADDED.equals(action)) {
String pkg=getPackageName(intent);int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);//We consider something to have changed regardless of whether//this is just an update, because the update is now finished//and the contents of the package may have changed.
mSomePackagesChanged = true;if (pkg != null) {
mAppearingPackages=mTempArray;
mTempArray[0] =pkg;if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
mModifiedPackages=mTempArray;
mChangeType=PACKAGE_UPDATING;
onPackageUpdateFinished(pkg, uid);
onPackageModified(pkg);
}else{
mChangeType=PACKAGE_PERMANENT_CHANGE;
onPackageAdded(pkg, uid);
}
onPackageAppeared(pkg, mChangeType);if (mChangeType ==PACKAGE_UPDATING) {synchronized(mUpdatingPackages) {
mUpdatingPackages.remove(pkg);
}
}
}
}else if(Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
String pkg=getPackageName(intent);int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);if (pkg != null) {
mDisappearingPackages=mTempArray;
mTempArray[0] =pkg;if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
mChangeType=PACKAGE_UPDATING;synchronized(mUpdatingPackages) {//not used for now//mUpdatingPackages.add(pkg);
}
onPackageUpdateStarted(pkg, uid);
}else{
mChangeType=PACKAGE_PERMANENT_CHANGE;//We only consider something to have changed if this is//not a replace; for a replace, we just need to consider//it when it is re-added.
mSomePackagesChanged = true;
onPackageRemoved(pkg, uid);if (intent.getBooleanExtra(Intent.EXTRA_REMOVED_FOR_ALL_USERS, false)) {
onPackageRemovedAllUsers(pkg, uid);
}
}
onPackageDisappeared(pkg, mChangeType);
}
}else if(Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
String pkg=getPackageName(intent);int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);
String[] components=intent.getStringArrayExtra(
Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);if (pkg != null) {
mModifiedPackages=mTempArray;
mTempArray[0] =pkg;
mChangeType=PACKAGE_PERMANENT_CHANGE;if(onPackageChanged(pkg, uid, components)) {
mSomePackagesChanged= true;
}
onPackageModified(pkg);
}
}else if(Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
mDisappearingPackages=intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
mChangeType=PACKAGE_TEMPORARY_CHANGE;boolean canRestart =onHandleForceStop(intent,
mDisappearingPackages,
intent.getIntExtra(Intent.EXTRA_UID,0), false);if(canRestart) setResultCode(Activity.RESULT_OK);
}else if(Intent.ACTION_PACKAGE_RESTARTED.equals(action)) {
mDisappearingPackages= newString[] {getPackageName(intent)};
mChangeType=PACKAGE_TEMPORARY_CHANGE;
onHandleForceStop(intent, mDisappearingPackages,
intent.getIntExtra(Intent.EXTRA_UID,0), true);
}else if(Intent.ACTION_UID_REMOVED.equals(action)) {
onUidRemoved(intent.getIntExtra(Intent.EXTRA_UID,0));
}else if(Intent.ACTION_USER_STOPPED.equals(action)) {if(intent.hasExtra(Intent.EXTRA_USER_HANDLE)) {
onHandleUserStop(intent, intent.getIntExtra(Intent.EXTRA_USER_HANDLE,0));
}
}else if(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
String[] pkgList=intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
mAppearingPackages=pkgList;
mChangeType= intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)?PACKAGE_UPDATING : PACKAGE_TEMPORARY_CHANGE;
mSomePackagesChanged= true;if (pkgList != null) {
onPackagesAvailable(pkgList);for (int i=0; i
onPackageAppeared(pkgList[i], mChangeType);
}
}
}else if(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
String[] pkgList=intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
mDisappearingPackages=pkgList;
mChangeType= intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)?PACKAGE_UPDATING : PACKAGE_TEMPORARY_CHANGE;
mSomePackagesChanged= true;if (pkgList != null) {
onPackagesUnavailable(pkgList);for (int i=0; i
onPackageDisappeared(pkgList[i], mChangeType);
}
}
}if(mSomePackagesChanged) {
onSomePackagesChanged();
}
onFinishPackageChanges();
mChangeUserId=UserHandle.USER_NULL;
}
}