1c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner/*
2c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * Copyright (C) 2014 The Android Open Source Project
3c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner *
4c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * Licensed under the Apache License, Version 2.0 (the "License");
5c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * you may not use this file except in compliance with the License.
6c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * You may obtain a copy of the License at
7c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner *
8c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner *      http://www.apache.org/licenses/LICENSE-2.0
9c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner *
10c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * Unless required by applicable law or agreed to in writing, software
11c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * distributed under the License is distributed on an "AS IS" BASIS,
12c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * See the License for the specific language governing permissions and
14c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * limitations under the License.
15c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner */
16c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner
170f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornpackage com.android.server.am;
180f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
190f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport java.io.File;
200f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport java.io.FileInputStream;
210f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport java.io.FileOutputStream;
2236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport java.util.HashMap;
230f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport java.util.Iterator;
2436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport java.util.Map;
250f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
260f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport org.xmlpull.v1.XmlPullParser;
270f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport org.xmlpull.v1.XmlPullParserException;
280f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport org.xmlpull.v1.XmlSerializer;
290f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
300f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport com.android.internal.util.FastXmlSerializer;
310f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
320f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.app.ActivityManager;
330f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.app.AppGlobals;
340f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.content.pm.ApplicationInfo;
350f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.content.pm.IPackageManager;
360f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.content.res.CompatibilityInfo;
370f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.os.Handler;
386f357d3284a833cc50a990e14b39f389b8972254Jeff Brownimport android.os.Looper;
390f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.os.Message;
400f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.os.RemoteException;
4139606a007a5b1309dd000234f2b8cf156c49fd0fDianne Hackbornimport android.util.AtomicFile;
420f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.util.Slog;
430f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackbornimport android.util.Xml;
440f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
45be4e6aaa0252dd7da28b7aa85beba982538efa46Dianne Hackbornpublic final class CompatModePackages {
460f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    private final String TAG = ActivityManagerService.TAG;
470f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    private final boolean DEBUG_CONFIGURATION = ActivityManagerService.DEBUG_CONFIGURATION;
480f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
490f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    private final ActivityManagerService mService;
500f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    private final AtomicFile mFile;
510f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
5236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    // Compatibility state: no longer ask user to select the mode.
5336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    public static final int COMPAT_FLAG_DONT_ASK = 1<<0;
5436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    // Compatibility state: compatibility mode is enabled.
5536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    public static final int COMPAT_FLAG_ENABLED = 1<<1;
5636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
5736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    private final HashMap<String, Integer> mPackages = new HashMap<String, Integer>();
580f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
5940c8db5a28e9abae2033facce1354e3677911fccDianne Hackborn    private static final int MSG_WRITE = ActivityManagerService.FIRST_COMPAT_MODE_MSG;
600f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
616f357d3284a833cc50a990e14b39f389b8972254Jeff Brown    private final CompatHandler mHandler;
626f357d3284a833cc50a990e14b39f389b8972254Jeff Brown
636f357d3284a833cc50a990e14b39f389b8972254Jeff Brown    private final class CompatHandler extends Handler {
646f357d3284a833cc50a990e14b39f389b8972254Jeff Brown        public CompatHandler(Looper looper) {
656f357d3284a833cc50a990e14b39f389b8972254Jeff Brown            super(looper, null, true);
666f357d3284a833cc50a990e14b39f389b8972254Jeff Brown        }
676f357d3284a833cc50a990e14b39f389b8972254Jeff Brown
686f357d3284a833cc50a990e14b39f389b8972254Jeff Brown        @Override
696f357d3284a833cc50a990e14b39f389b8972254Jeff Brown        public void handleMessage(Message msg) {
700f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            switch (msg.what) {
710f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                case MSG_WRITE:
720f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    saveCompatModes();
730f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    break;
740f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            }
750f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
760f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    };
770f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
786f357d3284a833cc50a990e14b39f389b8972254Jeff Brown    public CompatModePackages(ActivityManagerService service, File systemDir, Handler handler) {
790f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        mService = service;
800f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        mFile = new AtomicFile(new File(systemDir, "packages-compat.xml"));
816f357d3284a833cc50a990e14b39f389b8972254Jeff Brown        mHandler = new CompatHandler(handler.getLooper());
820f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
830f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        FileInputStream fis = null;
840f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        try {
850f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            fis = mFile.openRead();
860f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            XmlPullParser parser = Xml.newPullParser();
870f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            parser.setInput(fis, null);
880f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            int eventType = parser.getEventType();
892ac3cb7aef7c8a51cbeb6d34b648dedcb4363994Narayan Kamath            while (eventType != XmlPullParser.START_TAG &&
902ac3cb7aef7c8a51cbeb6d34b648dedcb4363994Narayan Kamath                    eventType != XmlPullParser.END_DOCUMENT) {
910f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                eventType = parser.next();
920f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            }
932ac3cb7aef7c8a51cbeb6d34b648dedcb4363994Narayan Kamath            if (eventType == XmlPullParser.END_DOCUMENT) {
942ac3cb7aef7c8a51cbeb6d34b648dedcb4363994Narayan Kamath                return;
952ac3cb7aef7c8a51cbeb6d34b648dedcb4363994Narayan Kamath            }
962ac3cb7aef7c8a51cbeb6d34b648dedcb4363994Narayan Kamath
970f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            String tagName = parser.getName();
980f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            if ("compat-packages".equals(tagName)) {
990f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                eventType = parser.next();
1000f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                do {
1010f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    if (eventType == XmlPullParser.START_TAG) {
1020f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                        tagName = parser.getName();
1030f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                        if (parser.getDepth() == 2) {
1040f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                            if ("pkg".equals(tagName)) {
1050f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                                String pkg = parser.getAttributeValue(null, "name");
1060f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                                if (pkg != null) {
10736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                                    String mode = parser.getAttributeValue(null, "mode");
10836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                                    int modeInt = 0;
10936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                                    if (mode != null) {
11036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                                        try {
11136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                                            modeInt = Integer.parseInt(mode);
11236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                                        } catch (NumberFormatException e) {
11336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                                        }
11436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                                    }
11536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                                    mPackages.put(pkg, modeInt);
1160f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                                }
1170f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                            }
1180f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                        }
1190f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    }
1200f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    eventType = parser.next();
1210f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                } while (eventType != XmlPullParser.END_DOCUMENT);
1220f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            }
1230f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        } catch (XmlPullParserException e) {
1240f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            Slog.w(TAG, "Error reading compat-packages", e);
1250f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        } catch (java.io.IOException e) {
1260f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            if (fis != null) Slog.w(TAG, "Error reading compat-packages", e);
1270f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        } finally {
1280f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            if (fis != null) {
1290f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                try {
1300f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    fis.close();
1310f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                } catch (java.io.IOException e1) {
1320f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                }
1330f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            }
1340f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
1350f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
1360f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
13736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    public HashMap<String, Integer> getPackages() {
1380f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        return mPackages;
1390f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
1400f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
14136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    private int getPackageFlags(String packageName) {
14236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        Integer flags = mPackages.get(packageName);
14336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        return flags != null ? flags : 0;
14436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    }
14536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
1468ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn    public void handlePackageAddedLocked(String packageName, boolean updated) {
1478ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        ApplicationInfo ai = null;
1488ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        try {
149483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani            ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0, 0);
1508ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        } catch (RemoteException e) {
1518ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        }
1528ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        if (ai == null) {
1538ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            return;
1548ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        }
1558ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        CompatibilityInfo ci = compatibilityInfoForPackageLocked(ai);
1568ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        final boolean mayCompat = !ci.alwaysSupportsScreen()
1578ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                && !ci.neverSupportsScreen();
1588ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn
159a9551706a279a798c91d8ef593b2acb16a30c682Dianne Hackborn        if (updated) {
1608ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            // Update -- if the app no longer can run in compat mode, clear
1618ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            // any current settings for it.
1628ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            if (!mayCompat && mPackages.containsKey(packageName)) {
1638ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                mPackages.remove(packageName);
1648ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                mHandler.removeMessages(MSG_WRITE);
1658ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                Message msg = mHandler.obtainMessage(MSG_WRITE);
1668ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                mHandler.sendMessageDelayed(msg, 10000);
1678ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            }
1688ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        }
1698ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn    }
1708ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn
1710f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    public CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
1722f0b17573d4324832f7a20402a3d2b5920bc4866Dianne Hackborn        CompatibilityInfo ci = new CompatibilityInfo(ai, mService.mConfiguration.screenLayout,
173df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                mService.mConfiguration.smallestScreenWidthDp,
17436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                (getPackageFlags(ai.packageName)&COMPAT_FLAG_ENABLED) != 0);
1752f0b17573d4324832f7a20402a3d2b5920bc4866Dianne Hackborn        //Slog.i(TAG, "*********** COMPAT FOR PKG " + ai.packageName + ": " + ci);
1762f0b17573d4324832f7a20402a3d2b5920bc4866Dianne Hackborn        return ci;
1770f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
1780f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
17936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    public int computeCompatModeLocked(ApplicationInfo ai) {
18036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        boolean enabled = (getPackageFlags(ai.packageName)&COMPAT_FLAG_ENABLED) != 0;
1810f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        CompatibilityInfo info = new CompatibilityInfo(ai,
182df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                mService.mConfiguration.screenLayout,
183df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                mService.mConfiguration.smallestScreenWidthDp, enabled);
1840f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        if (info.alwaysSupportsScreen()) {
1850f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            return ActivityManager.COMPAT_MODE_NEVER;
1860f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
1870f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        if (info.neverSupportsScreen()) {
1880f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            return ActivityManager.COMPAT_MODE_ALWAYS;
1890f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
1900f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        return enabled ? ActivityManager.COMPAT_MODE_ENABLED
1910f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                : ActivityManager.COMPAT_MODE_DISABLED;
1920f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
1930f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
19436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    public boolean getFrontActivityAskCompatModeLocked() {
195ce5f3cba6b95e1fbc800c0fc43d13bb830e87423Craig Mautner        ActivityRecord r = mService.getFocusedStack().topRunningActivityLocked(null);
19636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        if (r == null) {
19736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            return false;
19836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        }
19936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        return getPackageAskCompatModeLocked(r.packageName);
20036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    }
20136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
20236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    public boolean getPackageAskCompatModeLocked(String packageName) {
20336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        return (getPackageFlags(packageName)&COMPAT_FLAG_DONT_ASK) == 0;
20436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    }
20536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
20636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    public void setFrontActivityAskCompatModeLocked(boolean ask) {
207ce5f3cba6b95e1fbc800c0fc43d13bb830e87423Craig Mautner        ActivityRecord r = mService.getFocusedStack().topRunningActivityLocked(null);
20836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        if (r != null) {
20936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            setPackageAskCompatModeLocked(r.packageName, ask);
21036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        }
21136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    }
21236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
21336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    public void setPackageAskCompatModeLocked(String packageName, boolean ask) {
21436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        int curFlags = getPackageFlags(packageName);
21536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        int newFlags = ask ? (curFlags&~COMPAT_FLAG_DONT_ASK) : (curFlags|COMPAT_FLAG_DONT_ASK);
21636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        if (curFlags != newFlags) {
21736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            if (newFlags != 0) {
21836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                mPackages.put(packageName, newFlags);
21936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            } else {
22036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                mPackages.remove(packageName);
22136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            }
22236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            mHandler.removeMessages(MSG_WRITE);
22336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            Message msg = mHandler.obtainMessage(MSG_WRITE);
22436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            mHandler.sendMessageDelayed(msg, 10000);
22536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        }
22636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    }
22736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
2280f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    public int getFrontActivityScreenCompatModeLocked() {
229ce5f3cba6b95e1fbc800c0fc43d13bb830e87423Craig Mautner        ActivityRecord r = mService.getFocusedStack().topRunningActivityLocked(null);
2300f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        if (r == null) {
2310f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            return ActivityManager.COMPAT_MODE_UNKNOWN;
2320f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
2330f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        return computeCompatModeLocked(r.info.applicationInfo);
2340f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
2350f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
2360f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    public void setFrontActivityScreenCompatModeLocked(int mode) {
237ce5f3cba6b95e1fbc800c0fc43d13bb830e87423Craig Mautner        ActivityRecord r = mService.getFocusedStack().topRunningActivityLocked(null);
2380f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        if (r == null) {
2390f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            Slog.w(TAG, "setFrontActivityScreenCompatMode failed: no top activity");
2400f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            return;
2410f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
2420f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        setPackageScreenCompatModeLocked(r.info.applicationInfo, mode);
2430f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
2440f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
2450f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    public int getPackageScreenCompatModeLocked(String packageName) {
2460f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        ApplicationInfo ai = null;
2470f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        try {
248483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani            ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0, 0);
2490f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        } catch (RemoteException e) {
2500f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
2510f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        if (ai == null) {
2520f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            return ActivityManager.COMPAT_MODE_UNKNOWN;
2530f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
2540f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        return computeCompatModeLocked(ai);
2550f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
2560f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
2570f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    public void setPackageScreenCompatModeLocked(String packageName, int mode) {
2580f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        ApplicationInfo ai = null;
2590f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        try {
260483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani            ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0, 0);
2610f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        } catch (RemoteException e) {
2620f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
2630f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        if (ai == null) {
2640f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            Slog.w(TAG, "setPackageScreenCompatMode failed: unknown package " + packageName);
2650f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            return;
2660f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
2670f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        setPackageScreenCompatModeLocked(ai, mode);
2680f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
2690f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
2700f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    private void setPackageScreenCompatModeLocked(ApplicationInfo ai, int mode) {
2710f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        final String packageName = ai.packageName;
2720f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
27336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        int curFlags = getPackageFlags(packageName);
27436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
2750f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        boolean enable;
2760f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        switch (mode) {
2770f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            case ActivityManager.COMPAT_MODE_DISABLED:
2780f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                enable = false;
2790f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                break;
2800f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            case ActivityManager.COMPAT_MODE_ENABLED:
2810f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                enable = true;
2820f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                break;
2830f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            case ActivityManager.COMPAT_MODE_TOGGLE:
28436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                enable = (curFlags&COMPAT_FLAG_ENABLED) == 0;
2850f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                break;
2860f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            default:
2870f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                Slog.w(TAG, "Unknown screen compat mode req #" + mode + "; ignoring");
2880f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                return;
2890f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
29036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
29136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        int newFlags = curFlags;
2920f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        if (enable) {
29336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            newFlags |= COMPAT_FLAG_ENABLED;
2940f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        } else {
29536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            newFlags &= ~COMPAT_FLAG_ENABLED;
29636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        }
29736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
2988ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        CompatibilityInfo ci = compatibilityInfoForPackageLocked(ai);
2998ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        if (ci.alwaysSupportsScreen()) {
3008ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            Slog.w(TAG, "Ignoring compat mode change of " + packageName
3018ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                    + "; compatibility never needed");
3028ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            newFlags = 0;
3038ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        }
3048ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        if (ci.neverSupportsScreen()) {
3058ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            Slog.w(TAG, "Ignoring compat mode change of " + packageName
3068ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                    + "; compatibility always needed");
3078ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            newFlags = 0;
3088ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        }
3098ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn
31036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        if (newFlags != curFlags) {
31136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            if (newFlags != 0) {
31236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                mPackages.put(packageName, newFlags);
31336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            } else {
3140f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                mPackages.remove(packageName);
3150f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            }
3168ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn
3178ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            // Need to get compatibility info in new state.
3188ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            ci = compatibilityInfoForPackageLocked(ai);
3190f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
3200f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            mHandler.removeMessages(MSG_WRITE);
3210f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            Message msg = mHandler.obtainMessage(MSG_WRITE);
3220f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            mHandler.sendMessageDelayed(msg, 10000);
3230f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
324ce5f3cba6b95e1fbc800c0fc43d13bb830e87423Craig Mautner            final ActivityStack stack = mService.getFocusedStack();
32520e7227454bf6f3500c6eb97a17483dd8b764341Craig Mautner            ActivityRecord starting = stack.restartPackage(packageName);
3268ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn
3270f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            // Tell all processes that loaded this package about the change.
3280f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            for (int i=mService.mLruProcesses.size()-1; i>=0; i--) {
3290f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                ProcessRecord app = mService.mLruProcesses.get(i);
33078a369c90f61981c9d0ddd5fcbc77202bfbe74f6Dianne Hackborn                if (!app.pkgList.containsKey(packageName)) {
3310f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    continue;
3320f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                }
3330f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                try {
3340f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    if (app.thread != null) {
3350f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
3360f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                                + app.processName + " new compat " + ci);
3370f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                        app.thread.updatePackageCompatibilityInfo(packageName, ci);
3380f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    }
3390f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                } catch (Exception e) {
3400f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                }
3410f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            }
3420f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
3430f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            if (starting != null) {
34420e7227454bf6f3500c6eb97a17483dd8b764341Craig Mautner                stack.ensureActivityConfigurationLocked(starting, 0);
3450f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                // And we need to make sure at this point that all other activities
3460f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                // are made visible with the correct configuration.
34720e7227454bf6f3500c6eb97a17483dd8b764341Craig Mautner                stack.ensureActivitiesVisibleLocked(starting, 0);
3480f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            }
3490f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
3500f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
3510f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
3520f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    void saveCompatModes() {
35336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        HashMap<String, Integer> pkgs;
3540f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        synchronized (mService) {
35536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            pkgs = new HashMap<String, Integer>(mPackages);
3560f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
3570f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
3580f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        FileOutputStream fos = null;
3590f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
3600f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        try {
3610f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            fos = mFile.startWrite();
3620f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            XmlSerializer out = new FastXmlSerializer();
3630f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            out.setOutput(fos, "utf-8");
3640f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            out.startDocument(null, true);
3650f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
3660f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            out.startTag(null, "compat-packages");
3670f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
3680f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            final IPackageManager pm = AppGlobals.getPackageManager();
3690f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            final int screenLayout = mService.mConfiguration.screenLayout;
370df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            final int smallestScreenWidthDp = mService.mConfiguration.smallestScreenWidthDp;
37136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            final Iterator<Map.Entry<String, Integer>> it = pkgs.entrySet().iterator();
3720f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            while (it.hasNext()) {
37336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                Map.Entry<String, Integer> entry = it.next();
37436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                String pkg = entry.getKey();
37536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                int mode = entry.getValue();
37636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                if (mode == 0) {
37736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                    continue;
37836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                }
3790f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                ApplicationInfo ai = null;
3800f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                try {
381483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani                    ai = pm.getApplicationInfo(pkg, 0, 0);
3820f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                } catch (RemoteException e) {
3830f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                }
3840f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                if (ai == null) {
3850f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    continue;
3860f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                }
387df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                CompatibilityInfo info = new CompatibilityInfo(ai, screenLayout,
388df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                        smallestScreenWidthDp, false);
3890f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                if (info.alwaysSupportsScreen()) {
3900f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    continue;
3910f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                }
3920f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                if (info.neverSupportsScreen()) {
3930f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                    continue;
3940f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                }
3950f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                out.startTag(null, "pkg");
3960f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                out.attribute(null, "name", pkg);
39736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                out.attribute(null, "mode", Integer.toString(mode));
3980f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                out.endTag(null, "pkg");
3990f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            }
4000f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
4010f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            out.endTag(null, "compat-packages");
4020f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            out.endDocument();
4030f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
4040f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            mFile.finishWrite(fos);
4050f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        } catch (java.io.IOException e1) {
4060f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            Slog.w(TAG, "Error writing compat packages", e1);
4070f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            if (fos != null) {
4080f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                mFile.failWrite(fos);
4090f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn            }
4100f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn        }
4110f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
4120f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn}
413