Compatibility.java revision 58f27f3da5487279c18ddada93be0bee682b758f
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.musicfx; 18 19import android.app.Activity; 20import android.app.IntentService; 21import android.content.BroadcastReceiver; 22import android.content.ComponentName; 23import android.content.Context; 24import android.content.Intent; 25import android.content.SharedPreferences; 26import android.content.SharedPreferences.Editor; 27import android.content.pm.PackageManager; 28import android.content.pm.ResolveInfo; 29import android.media.audiofx.AudioEffect; 30import android.net.Uri; 31import android.os.Bundle; 32import android.util.Log; 33 34import java.util.List; 35 36/** 37 * Provide backwards compatibility for existing control panels. 38 * There are two major parts to this: 39 * - a BroadcastReceiver that listens for installed or removed packages, and 40 * enables or disables control panel receivers as needed to ensure that only 41 * one control panel package will receive the broadcasts that applications end 42 * - a high priority control panel activity that redirects to the currently 43 * selected control panel activity 44 * 45 */ 46public class Compatibility { 47 48 private final static String TAG = "MusicFXCompat"; 49 // run "setprop log.tag.MusicFXCompat DEBUG" to turn on logging 50 private final static boolean LOG = Log.isLoggable(TAG, Log.DEBUG); 51 52 53 /** 54 * This activity has an intent filter with the highest possible priority, so 55 * it will always be chosen. It then looks up the correct control panel to 56 * use and launches that. 57 */ 58 public static class Redirector extends Activity { 59 60 @Override 61 public void onCreate(final Bundle savedInstanceState) { 62 super.onCreate(savedInstanceState); 63 log("Compatibility Activity called from " + getCallingPackage()); 64 Intent i = new Intent(getIntent()); 65 i.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); 66 SharedPreferences pref = getSharedPreferences("musicfx", MODE_PRIVATE); 67 String defPackage = pref.getString("defaultpanelpackage", null); 68 String defName = pref.getString("defaultpanelname", null); 69 log("read " + defPackage + "/" + defName + " as default"); 70 if (defPackage == null || defName == null) { 71 Log.e(TAG, "no default set!"); 72 // TODO pick a default here? 73 finish(); 74 return; 75 } else { 76 i.setComponent(new ComponentName(defPackage, defName)); 77 } 78 startActivity(i); 79 finish(); 80 } 81 } 82 83 /** 84 * This BroadcastReceiver responds to BOOT_COMPLETED, PACKAGE_ADDED, 85 * PACKAGE_REPLACED and PACKAGE_REMOVED intents. When run, it checks 86 * to see whether the active control panel needs to be updated: 87 * - if there is no default, it picks one 88 * - if a new control panel is installed, it becomes the default 89 * It then enables the open/close receivers in the active control panel, 90 * and disables them in the others. 91 */ 92 public static class Receiver extends BroadcastReceiver { 93 94 @Override 95 public void onReceive(final Context context, final Intent intent) { 96 97 Intent updateIntent = new Intent(context, Service.class); 98 updateIntent.putExtra("reason", intent); 99 context.startService(updateIntent); 100 } 101 102 public static class Service extends IntentService { 103 104 PackageManager mPackageManager; 105 106 public Service() { 107 super("CompatibilityService"); 108 } 109 110 @Override 111 protected void onHandleIntent(final Intent intent) { 112 if (mPackageManager == null) { 113 mPackageManager = getPackageManager(); 114 } 115 Intent packageIntent = intent.getParcelableExtra("reason"); 116 Bundle b = packageIntent.getExtras(); 117 if (b != null) b.size(); 118 log("intentservice saw: " + packageIntent + " " + b); 119 // TODO, be smarter about package upgrades (which results in three 120 // broadcasts: removed, added, replaced) 121 Uri packageUri = packageIntent.getData(); 122 String updatedPackage = null; 123 if (packageUri != null) { 124 updatedPackage = packageUri.toString().substring(8); 125 pickDefaultControlPanel(updatedPackage); 126 } 127 } 128 129 private void pickDefaultControlPanel(String updatedPackage) { 130 131 ResolveInfo defPanel = null; 132 ResolveInfo otherPanel = null; 133 ResolveInfo thisPanel = null; 134 Intent i = new Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL); 135 List<ResolveInfo> ris = mPackageManager.queryIntentActivities(i, PackageManager.GET_DISABLED_COMPONENTS); 136 log("found: " + ris.size()); 137 ResolveInfo ri = mPackageManager.resolveActivity(i, 0); 138 log("resolved: " + ri + " " + (ri != null ? ri.activityInfo.enabled : "")); 139 for (ResolveInfo foo: ris) { 140 if (foo.activityInfo.name.equals(Compatibility.Redirector.class.getName())) { 141 log("skipping " + foo); 142 continue; 143 } 144 log("considering " + foo); 145 if (ri != null && foo.activityInfo.name.equals(ri.activityInfo.name) && 146 foo.activityInfo.packageName.equals(ri.activityInfo.packageName) && 147 foo.activityInfo.enabled) { 148 log("default: " + ri.activityInfo.name); 149 defPanel = foo; 150 break; 151 } else if (foo.activityInfo.packageName.equals(updatedPackage)) { 152 log("choosing newly installed package " + updatedPackage); 153 otherPanel = foo; 154 } else if (otherPanel == null && !foo.activityInfo.packageName.equals(getPackageName())) { 155 otherPanel = foo; 156 } else { 157 thisPanel = foo; 158 } 159 } 160 161 if (defPanel == null) { 162 // pick a default control panel 163 if (otherPanel == null) { 164 if (thisPanel == null) { 165 Log.e(TAG, "No control panels found!"); 166 return; 167 } 168 otherPanel = thisPanel; 169 } 170 defPanel = otherPanel; 171 } 172 173 // Now that we have selected a default control panel activity, ensure 174 // that the broadcast receiver(s) in that same package are enabled, 175 // and the ones in the other packages are disabled. 176 String defPackage = defPanel.activityInfo.packageName; 177 i = new Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION); 178 ris = mPackageManager.queryBroadcastReceivers(i, PackageManager.GET_DISABLED_COMPONENTS); 179 setupReceivers(ris, defPackage); 180 // The open and close receivers are likely the same, but they may not be. 181 i = new Intent(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION); 182 ris = mPackageManager.queryBroadcastReceivers(i, PackageManager.GET_DISABLED_COMPONENTS); 183 setupReceivers(ris, defPackage); 184 185 // Write the selected default to the prefs so that the Redirector activity 186 // knows which one to use. 187 SharedPreferences pref = getSharedPreferences("musicfx", MODE_PRIVATE); 188 Editor ed = pref.edit(); 189 ed.putString("defaultpanelpackage", defPackage); 190 ed.putString("defaultpanelname", defPanel.activityInfo.name); 191 ed.commit(); 192 log("wrote " + defPackage + "/" + defPanel.activityInfo.name + " as default"); 193 } 194 195 private void setupReceivers(List<ResolveInfo> ris, String defPackage) { 196 for (ResolveInfo foo: ris) { 197 ComponentName comp = new ComponentName(foo.activityInfo.packageName, foo.activityInfo.name); 198 if (foo.activityInfo.packageName.equals(defPackage)) { 199 log("enabling receiver " + foo); 200 mPackageManager.setComponentEnabledSetting(comp, 201 PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 202 PackageManager.DONT_KILL_APP); 203 } else { 204 log("disabling receiver " + foo); 205 mPackageManager.setComponentEnabledSetting(comp, 206 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 207 PackageManager.DONT_KILL_APP); 208 } 209 } 210 } 211 } 212 } 213 214 private static void log(String out) { 215 if (LOG) { 216 Log.d(TAG, out); 217 } 218 } 219} 220