10f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornpackage com.android.server.am;
20f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
30f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport java.io.File;
40f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport java.io.FileInputStream;
50f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport java.io.FileOutputStream;
636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport java.util.HashMap;
70f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport java.util.HashSet;
80f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport java.util.Iterator;
936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport java.util.Map;
100f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
110f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport org.xmlpull.v1.XmlPullParser;
120f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport org.xmlpull.v1.XmlPullParserException;
130f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport org.xmlpull.v1.XmlSerializer;
140f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
150f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport com.android.internal.os.AtomicFile;
160f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport com.android.internal.util.FastXmlSerializer;
170f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
180f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.app.ActivityManager;
190f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.app.AppGlobals;
208ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackbornimport android.content.pm.ActivityInfo;
210f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.content.pm.ApplicationInfo;
220f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.content.pm.IPackageManager;
230f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.content.res.CompatibilityInfo;
240f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.os.Handler;
250f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.os.Message;
260f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.os.RemoteException;
270f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.util.Slog;
280f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.util.Xml;
290f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
300f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornpublic class CompatModePackages {
310f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    private final String TAG = ActivityManagerService.TAG;
320f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    private final boolean DEBUG_CONFIGURATION = ActivityManagerService.DEBUG_CONFIGURATION;
330f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
340f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    private final ActivityManagerService mService;
350f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    private final AtomicFile mFile;
360f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
3736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    // Compatibility state: no longer ask user to select the mode.
3836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    public static final int COMPAT_FLAG_DONT_ASK = 1<<0;
3936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    // Compatibility state: compatibility mode is enabled.
4036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    public static final int COMPAT_FLAG_ENABLED = 1<<1;
4136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
4236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    private final HashMap<String, Integer> mPackages = new HashMap<String, Integer>();
430f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
440f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    private static final int MSG_WRITE = 1;
450f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
460f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    private final Handler mHandler = new Handler() {
470f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        @Override public void handleMessage(Message msg) {
480f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            switch (msg.what) {
490f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                case MSG_WRITE:
500f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    saveCompatModes();
510f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    break;
520f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                default:
530f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    super.handleMessage(msg);
540f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    break;
550f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            }
560f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
570f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    };
580f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
590f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    public CompatModePackages(ActivityManagerService service, File systemDir) {
600f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        mService = service;
610f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        mFile = new AtomicFile(new File(systemDir, "packages-compat.xml"));
620f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
630f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        FileInputStream fis = null;
640f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        try {
650f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            fis = mFile.openRead();
660f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            XmlPullParser parser = Xml.newPullParser();
670f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            parser.setInput(fis, null);
680f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            int eventType = parser.getEventType();
690f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            while (eventType != XmlPullParser.START_TAG) {
700f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                eventType = parser.next();
710f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            }
720f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            String tagName = parser.getName();
730f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            if ("compat-packages".equals(tagName)) {
740f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                eventType = parser.next();
750f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                do {
760f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    if (eventType == XmlPullParser.START_TAG) {
770f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                        tagName = parser.getName();
780f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                        if (parser.getDepth() == 2) {
790f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                            if ("pkg".equals(tagName)) {
800f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                                String pkg = parser.getAttributeValue(null, "name");
810f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                                if (pkg != null) {
8236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                                    String mode = parser.getAttributeValue(null, "mode");
8336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                                    int modeInt = 0;
8436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                                    if (mode != null) {
8536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                                        try {
8636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                                            modeInt = Integer.parseInt(mode);
8736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                                        } catch (NumberFormatException e) {
8836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                                        }
8936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                                    }
9036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                                    mPackages.put(pkg, modeInt);
910f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                                }
920f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                            }
930f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                        }
940f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    }
950f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    eventType = parser.next();
960f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                } while (eventType != XmlPullParser.END_DOCUMENT);
970f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            }
980f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        } catch (XmlPullParserException e) {
990f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            Slog.w(TAG, "Error reading compat-packages", e);
1000f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        } catch (java.io.IOException e) {
1010f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            if (fis != null) Slog.w(TAG, "Error reading compat-packages", e);
1020f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        } finally {
1030f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            if (fis != null) {
1040f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                try {
1050f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    fis.close();
1060f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                } catch (java.io.IOException e1) {
1070f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                }
1080f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            }
1090f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
1100f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
1110f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
11236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    public HashMap<String, Integer> getPackages() {
1130f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        return mPackages;
1140f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
1150f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
11636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    private int getPackageFlags(String packageName) {
11736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        Integer flags = mPackages.get(packageName);
11836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        return flags != null ? flags : 0;
11936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    }
12036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
1218ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn    public void handlePackageAddedLocked(String packageName, boolean updated) {
1228ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        ApplicationInfo ai = null;
1238ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        try {
1248ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0);
1258ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        } catch (RemoteException e) {
1268ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        }
1278ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        if (ai == null) {
1288ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            return;
1298ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        }
1308ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        CompatibilityInfo ci = compatibilityInfoForPackageLocked(ai);
1318ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        final boolean mayCompat = !ci.alwaysSupportsScreen()
1328ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                && !ci.neverSupportsScreen();
1338ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn
134a9551706a279a798c91d8ef593b2acb16a30c682Dianne Hackborn        if (updated) {
1358ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            // Update -- if the app no longer can run in compat mode, clear
1368ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            // any current settings for it.
1378ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            if (!mayCompat && mPackages.containsKey(packageName)) {
1388ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                mPackages.remove(packageName);
1398ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                mHandler.removeMessages(MSG_WRITE);
1408ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                Message msg = mHandler.obtainMessage(MSG_WRITE);
1418ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                mHandler.sendMessageDelayed(msg, 10000);
1428ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            }
1438ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        }
1448ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn    }
1458ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn
1460f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    public CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
1472f0b17573d4324832f7a20402a3d2b5920bc4866Dianne Hackborn        CompatibilityInfo ci = new CompatibilityInfo(ai, mService.mConfiguration.screenLayout,
148df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                mService.mConfiguration.smallestScreenWidthDp,
14936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                (getPackageFlags(ai.packageName)&COMPAT_FLAG_ENABLED) != 0);
1502f0b17573d4324832f7a20402a3d2b5920bc4866Dianne Hackborn        //Slog.i(TAG, "*********** COMPAT FOR PKG " + ai.packageName + ": " + ci);
1512f0b17573d4324832f7a20402a3d2b5920bc4866Dianne Hackborn        return ci;
1520f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
1530f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
15436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    public int computeCompatModeLocked(ApplicationInfo ai) {
15536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        boolean enabled = (getPackageFlags(ai.packageName)&COMPAT_FLAG_ENABLED) != 0;
1560f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        CompatibilityInfo info = new CompatibilityInfo(ai,
157df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                mService.mConfiguration.screenLayout,
158df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                mService.mConfiguration.smallestScreenWidthDp, enabled);
1590f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        if (info.alwaysSupportsScreen()) {
1600f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            return ActivityManager.COMPAT_MODE_NEVER;
1610f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
1620f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        if (info.neverSupportsScreen()) {
1630f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            return ActivityManager.COMPAT_MODE_ALWAYS;
1640f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
1650f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        return enabled ? ActivityManager.COMPAT_MODE_ENABLED
1660f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                : ActivityManager.COMPAT_MODE_DISABLED;
1670f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
1680f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
16936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    public boolean getFrontActivityAskCompatModeLocked() {
17036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        ActivityRecord r = mService.mMainStack.topRunningActivityLocked(null);
17136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        if (r == null) {
17236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            return false;
17336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        }
17436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        return getPackageAskCompatModeLocked(r.packageName);
17536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    }
17636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
17736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    public boolean getPackageAskCompatModeLocked(String packageName) {
17836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        return (getPackageFlags(packageName)&COMPAT_FLAG_DONT_ASK) == 0;
17936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    }
18036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
18136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    public void setFrontActivityAskCompatModeLocked(boolean ask) {
18236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        ActivityRecord r = mService.mMainStack.topRunningActivityLocked(null);
18336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        if (r != null) {
18436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            setPackageAskCompatModeLocked(r.packageName, ask);
18536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        }
18636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    }
18736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
18836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    public void setPackageAskCompatModeLocked(String packageName, boolean ask) {
18936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        int curFlags = getPackageFlags(packageName);
19036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        int newFlags = ask ? (curFlags&~COMPAT_FLAG_DONT_ASK) : (curFlags|COMPAT_FLAG_DONT_ASK);
19136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        if (curFlags != newFlags) {
19236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            if (newFlags != 0) {
19336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                mPackages.put(packageName, newFlags);
19436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            } else {
19536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                mPackages.remove(packageName);
19636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            }
19736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            mHandler.removeMessages(MSG_WRITE);
19836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            Message msg = mHandler.obtainMessage(MSG_WRITE);
19936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            mHandler.sendMessageDelayed(msg, 10000);
20036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        }
20136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    }
20236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
2030f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    public int getFrontActivityScreenCompatModeLocked() {
2040f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        ActivityRecord r = mService.mMainStack.topRunningActivityLocked(null);
2050f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        if (r == null) {
2060f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            return ActivityManager.COMPAT_MODE_UNKNOWN;
2070f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
2080f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        return computeCompatModeLocked(r.info.applicationInfo);
2090f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
2100f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
2110f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    public void setFrontActivityScreenCompatModeLocked(int mode) {
2120f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        ActivityRecord r = mService.mMainStack.topRunningActivityLocked(null);
2130f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        if (r == null) {
2140f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            Slog.w(TAG, "setFrontActivityScreenCompatMode failed: no top activity");
2150f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            return;
2160f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
2170f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        setPackageScreenCompatModeLocked(r.info.applicationInfo, mode);
2180f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
2190f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
2200f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    public int getPackageScreenCompatModeLocked(String packageName) {
2210f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        ApplicationInfo ai = null;
2220f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        try {
2230f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0);
2240f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        } catch (RemoteException e) {
2250f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
2260f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        if (ai == null) {
2270f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            return ActivityManager.COMPAT_MODE_UNKNOWN;
2280f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
2290f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        return computeCompatModeLocked(ai);
2300f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
2310f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
2320f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    public void setPackageScreenCompatModeLocked(String packageName, int mode) {
2330f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        ApplicationInfo ai = null;
2340f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        try {
2350f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0);
2360f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        } catch (RemoteException e) {
2370f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
2380f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        if (ai == null) {
2390f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            Slog.w(TAG, "setPackageScreenCompatMode failed: unknown package " + packageName);
2400f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            return;
2410f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
2420f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        setPackageScreenCompatModeLocked(ai, mode);
2430f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
2440f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
2450f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    private void setPackageScreenCompatModeLocked(ApplicationInfo ai, int mode) {
2460f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        final String packageName = ai.packageName;
2470f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
24836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        int curFlags = getPackageFlags(packageName);
24936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
2500f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        boolean enable;
2510f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        switch (mode) {
2520f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            case ActivityManager.COMPAT_MODE_DISABLED:
2530f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                enable = false;
2540f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                break;
2550f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            case ActivityManager.COMPAT_MODE_ENABLED:
2560f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                enable = true;
2570f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                break;
2580f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            case ActivityManager.COMPAT_MODE_TOGGLE:
25936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                enable = (curFlags&COMPAT_FLAG_ENABLED) == 0;
2600f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                break;
2610f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            default:
2620f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                Slog.w(TAG, "Unknown screen compat mode req #" + mode + "; ignoring");
2630f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                return;
2640f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
26536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
26636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        int newFlags = curFlags;
2670f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        if (enable) {
26836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            newFlags |= COMPAT_FLAG_ENABLED;
2690f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        } else {
27036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            newFlags &= ~COMPAT_FLAG_ENABLED;
27136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        }
27236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
2738ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        CompatibilityInfo ci = compatibilityInfoForPackageLocked(ai);
2748ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        if (ci.alwaysSupportsScreen()) {
2758ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            Slog.w(TAG, "Ignoring compat mode change of " + packageName
2768ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                    + "; compatibility never needed");
2778ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            newFlags = 0;
2788ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        }
2798ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        if (ci.neverSupportsScreen()) {
2808ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            Slog.w(TAG, "Ignoring compat mode change of " + packageName
2818ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                    + "; compatibility always needed");
2828ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            newFlags = 0;
2838ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        }
2848ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn
28536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        if (newFlags != curFlags) {
28636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            if (newFlags != 0) {
28736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                mPackages.put(packageName, newFlags);
28836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            } else {
2890f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                mPackages.remove(packageName);
2900f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            }
2918ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn
2928ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            // Need to get compatibility info in new state.
2938ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            ci = compatibilityInfoForPackageLocked(ai);
2940f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
2950f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            mHandler.removeMessages(MSG_WRITE);
2960f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            Message msg = mHandler.obtainMessage(MSG_WRITE);
2970f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            mHandler.sendMessageDelayed(msg, 10000);
2980f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
2998ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            ActivityRecord starting = mService.mMainStack.topRunningActivityLocked(null);
3008ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn
3018ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            // All activities that came from the package must be
3028ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            // restarted as if there was a config change.
3038ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            for (int i=mService.mMainStack.mHistory.size()-1; i>=0; i--) {
3048ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                ActivityRecord a = (ActivityRecord)mService.mMainStack.mHistory.get(i);
3058ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                if (a.info.packageName.equals(packageName)) {
3068ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                    a.forceNewConfig = true;
3078ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                    if (starting != null && a == starting && a.visible) {
3088ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                        a.startFreezingScreenLocked(starting.app,
3098ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                                ActivityInfo.CONFIG_SCREEN_LAYOUT);
3108ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                    }
3118ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                }
3128ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            }
3138ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn
3140f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            // Tell all processes that loaded this package about the change.
3150f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            for (int i=mService.mLruProcesses.size()-1; i>=0; i--) {
3160f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                ProcessRecord app = mService.mLruProcesses.get(i);
3170f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                if (!app.pkgList.contains(packageName)) {
3180f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    continue;
3190f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                }
3200f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                try {
3210f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    if (app.thread != null) {
3220f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
3230f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                                + app.processName + " new compat " + ci);
3240f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                        app.thread.updatePackageCompatibilityInfo(packageName, ci);
3250f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    }
3260f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                } catch (Exception e) {
3270f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                }
3280f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            }
3290f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
3300f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            if (starting != null) {
3310f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                mService.mMainStack.ensureActivityConfigurationLocked(starting, 0);
3320f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                // And we need to make sure at this point that all other activities
3330f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                // are made visible with the correct configuration.
3340f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                mService.mMainStack.ensureActivitiesVisibleLocked(starting, 0);
3350f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            }
3360f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
3370f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
3380f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
3390f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    void saveCompatModes() {
34036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        HashMap<String, Integer> pkgs;
3410f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        synchronized (mService) {
34236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            pkgs = new HashMap<String, Integer>(mPackages);
3430f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
3440f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
3450f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        FileOutputStream fos = null;
3460f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
3470f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        try {
3480f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            fos = mFile.startWrite();
3490f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            XmlSerializer out = new FastXmlSerializer();
3500f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            out.setOutput(fos, "utf-8");
3510f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            out.startDocument(null, true);
3520f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
3530f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            out.startTag(null, "compat-packages");
3540f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
3550f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            final IPackageManager pm = AppGlobals.getPackageManager();
3560f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            final int screenLayout = mService.mConfiguration.screenLayout;
357df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            final int smallestScreenWidthDp = mService.mConfiguration.smallestScreenWidthDp;
35836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            final Iterator<Map.Entry<String, Integer>> it = pkgs.entrySet().iterator();
3590f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            while (it.hasNext()) {
36036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                Map.Entry<String, Integer> entry = it.next();
36136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                String pkg = entry.getKey();
36236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                int mode = entry.getValue();
36336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                if (mode == 0) {
36436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                    continue;
36536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                }
3660f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                ApplicationInfo ai = null;
3670f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                try {
3680f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    ai = pm.getApplicationInfo(pkg, 0);
3690f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                } catch (RemoteException e) {
3700f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                }
3710f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                if (ai == null) {
3720f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    continue;
3730f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                }
374df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                CompatibilityInfo info = new CompatibilityInfo(ai, screenLayout,
375df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                        smallestScreenWidthDp, false);
3760f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                if (info.alwaysSupportsScreen()) {
3770f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    continue;
3780f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                }
3790f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                if (info.neverSupportsScreen()) {
3800f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    continue;
3810f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                }
3820f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                out.startTag(null, "pkg");
3830f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                out.attribute(null, "name", pkg);
38436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                out.attribute(null, "mode", Integer.toString(mode));
3850f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                out.endTag(null, "pkg");
3860f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            }
3870f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
3880f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            out.endTag(null, "compat-packages");
3890f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            out.endDocument();
3900f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
3910f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            mFile.finishWrite(fos);
3920f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        } catch (java.io.IOException e1) {
3930f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            Slog.w(TAG, "Error writing compat packages", e1);
3940f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            if (fos != null) {
3950f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                mFile.failWrite(fos);
3960f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            }
3970f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
3980f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
3990f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn}
400