xref: /aosp_15_r20/external/lzma/CPP/7zip/Compress/Rar3Decoder.h (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // Rar3Decoder.h
2*f6dc9357SAndroid Build Coastguard Worker // According to unRAR license, this code may not be used to develop
3*f6dc9357SAndroid Build Coastguard Worker // a program that creates RAR archives
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker /* This code uses Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #ifndef ZIP7_INC_COMPRESS_RAR3_DECODER_H
8*f6dc9357SAndroid Build Coastguard Worker #define ZIP7_INC_COMPRESS_RAR3_DECODER_H
9*f6dc9357SAndroid Build Coastguard Worker 
10*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/Ppmd7.h"
11*f6dc9357SAndroid Build Coastguard Worker 
12*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyCom.h"
13*f6dc9357SAndroid Build Coastguard Worker 
14*f6dc9357SAndroid Build Coastguard Worker #include "../ICoder.h"
15*f6dc9357SAndroid Build Coastguard Worker 
16*f6dc9357SAndroid Build Coastguard Worker #include "../Common/InBuffer.h"
17*f6dc9357SAndroid Build Coastguard Worker 
18*f6dc9357SAndroid Build Coastguard Worker #include "BitmDecoder.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "HuffmanDecoder.h"
20*f6dc9357SAndroid Build Coastguard Worker #include "Rar3Vm.h"
21*f6dc9357SAndroid Build Coastguard Worker 
22*f6dc9357SAndroid Build Coastguard Worker namespace NCompress {
23*f6dc9357SAndroid Build Coastguard Worker namespace NRar3 {
24*f6dc9357SAndroid Build Coastguard Worker 
25*f6dc9357SAndroid Build Coastguard Worker const unsigned kNumHuffmanBits = 15;
26*f6dc9357SAndroid Build Coastguard Worker 
27*f6dc9357SAndroid Build Coastguard Worker const UInt32 kWindowSize = 1 << 22;
28*f6dc9357SAndroid Build Coastguard Worker const UInt32 kWindowMask = kWindowSize - 1;
29*f6dc9357SAndroid Build Coastguard Worker 
30*f6dc9357SAndroid Build Coastguard Worker const unsigned kNumReps = 4;
31*f6dc9357SAndroid Build Coastguard Worker const unsigned kNumLen2Symbols = 8;
32*f6dc9357SAndroid Build Coastguard Worker const unsigned kLenTableSize = 28;
33*f6dc9357SAndroid Build Coastguard Worker const unsigned kMainTableSize = 256 + 3 + kNumReps + kNumLen2Symbols + kLenTableSize;
34*f6dc9357SAndroid Build Coastguard Worker const unsigned kDistTableSize = 60;
35*f6dc9357SAndroid Build Coastguard Worker 
36*f6dc9357SAndroid Build Coastguard Worker const unsigned kNumAlignBits = 4;
37*f6dc9357SAndroid Build Coastguard Worker const unsigned kAlignTableSize = (1 << kNumAlignBits) + 1;
38*f6dc9357SAndroid Build Coastguard Worker 
39*f6dc9357SAndroid Build Coastguard Worker const unsigned kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize + kLenTableSize;
40*f6dc9357SAndroid Build Coastguard Worker 
41*f6dc9357SAndroid Build Coastguard Worker class CBitDecoder
42*f6dc9357SAndroid Build Coastguard Worker {
43*f6dc9357SAndroid Build Coastguard Worker   UInt32 _value;
44*f6dc9357SAndroid Build Coastguard Worker   unsigned _bitPos;
45*f6dc9357SAndroid Build Coastguard Worker public:
46*f6dc9357SAndroid Build Coastguard Worker   CInBuffer Stream;
47*f6dc9357SAndroid Build Coastguard Worker 
Create(UInt32 bufSize)48*f6dc9357SAndroid Build Coastguard Worker   bool Create(UInt32 bufSize) { return Stream.Create(bufSize); }
SetStream(ISequentialInStream * inStream)49*f6dc9357SAndroid Build Coastguard Worker   void SetStream(ISequentialInStream *inStream) { Stream.SetStream(inStream);}
50*f6dc9357SAndroid Build Coastguard Worker 
Init()51*f6dc9357SAndroid Build Coastguard Worker   void Init()
52*f6dc9357SAndroid Build Coastguard Worker   {
53*f6dc9357SAndroid Build Coastguard Worker     Stream.Init();
54*f6dc9357SAndroid Build Coastguard Worker     _bitPos = 0;
55*f6dc9357SAndroid Build Coastguard Worker     _value = 0;
56*f6dc9357SAndroid Build Coastguard Worker   }
57*f6dc9357SAndroid Build Coastguard Worker 
ExtraBitsWereRead()58*f6dc9357SAndroid Build Coastguard Worker   bool ExtraBitsWereRead() const
59*f6dc9357SAndroid Build Coastguard Worker   {
60*f6dc9357SAndroid Build Coastguard Worker     return (Stream.NumExtraBytes > 4 || _bitPos < (Stream.NumExtraBytes << 3));
61*f6dc9357SAndroid Build Coastguard Worker   }
62*f6dc9357SAndroid Build Coastguard Worker 
GetProcessedSize()63*f6dc9357SAndroid Build Coastguard Worker   UInt64 GetProcessedSize() const { return Stream.GetProcessedSize() - (_bitPos >> 3); }
64*f6dc9357SAndroid Build Coastguard Worker 
AlignToByte()65*f6dc9357SAndroid Build Coastguard Worker   void AlignToByte()
66*f6dc9357SAndroid Build Coastguard Worker   {
67*f6dc9357SAndroid Build Coastguard Worker     _bitPos &= ~(unsigned)7;
68*f6dc9357SAndroid Build Coastguard Worker     _value = _value & ((1 << _bitPos) - 1);
69*f6dc9357SAndroid Build Coastguard Worker   }
70*f6dc9357SAndroid Build Coastguard Worker 
71*f6dc9357SAndroid Build Coastguard Worker   Z7_FORCE_INLINE
GetValue(unsigned numBits)72*f6dc9357SAndroid Build Coastguard Worker   UInt32 GetValue(unsigned numBits)
73*f6dc9357SAndroid Build Coastguard Worker   {
74*f6dc9357SAndroid Build Coastguard Worker     if (_bitPos < numBits)
75*f6dc9357SAndroid Build Coastguard Worker     {
76*f6dc9357SAndroid Build Coastguard Worker       _bitPos += 8;
77*f6dc9357SAndroid Build Coastguard Worker       _value = (_value << 8) | Stream.ReadByte();
78*f6dc9357SAndroid Build Coastguard Worker       if (_bitPos < numBits)
79*f6dc9357SAndroid Build Coastguard Worker       {
80*f6dc9357SAndroid Build Coastguard Worker         _bitPos += 8;
81*f6dc9357SAndroid Build Coastguard Worker         _value = (_value << 8) | Stream.ReadByte();
82*f6dc9357SAndroid Build Coastguard Worker       }
83*f6dc9357SAndroid Build Coastguard Worker     }
84*f6dc9357SAndroid Build Coastguard Worker     return _value >> (_bitPos - numBits);
85*f6dc9357SAndroid Build Coastguard Worker   }
86*f6dc9357SAndroid Build Coastguard Worker 
87*f6dc9357SAndroid Build Coastguard Worker   Z7_FORCE_INLINE
GetValue_InHigh32bits()88*f6dc9357SAndroid Build Coastguard Worker   UInt32 GetValue_InHigh32bits()
89*f6dc9357SAndroid Build Coastguard Worker   {
90*f6dc9357SAndroid Build Coastguard Worker     return GetValue(kNumHuffmanBits) << (32 - kNumHuffmanBits);
91*f6dc9357SAndroid Build Coastguard Worker   }
92*f6dc9357SAndroid Build Coastguard Worker 
93*f6dc9357SAndroid Build Coastguard Worker 
94*f6dc9357SAndroid Build Coastguard Worker   Z7_FORCE_INLINE
MovePos(unsigned numBits)95*f6dc9357SAndroid Build Coastguard Worker   void MovePos(unsigned numBits)
96*f6dc9357SAndroid Build Coastguard Worker   {
97*f6dc9357SAndroid Build Coastguard Worker     _bitPos -= numBits;
98*f6dc9357SAndroid Build Coastguard Worker     _value = _value & ((1 << _bitPos) - 1);
99*f6dc9357SAndroid Build Coastguard Worker   }
100*f6dc9357SAndroid Build Coastguard Worker 
ReadBits(unsigned numBits)101*f6dc9357SAndroid Build Coastguard Worker   UInt32 ReadBits(unsigned numBits)
102*f6dc9357SAndroid Build Coastguard Worker   {
103*f6dc9357SAndroid Build Coastguard Worker     const UInt32 res = GetValue(numBits);
104*f6dc9357SAndroid Build Coastguard Worker     MovePos(numBits);
105*f6dc9357SAndroid Build Coastguard Worker     return res;
106*f6dc9357SAndroid Build Coastguard Worker   }
107*f6dc9357SAndroid Build Coastguard Worker 
ReadBits_upto8(unsigned numBits)108*f6dc9357SAndroid Build Coastguard Worker   UInt32 ReadBits_upto8(unsigned numBits)
109*f6dc9357SAndroid Build Coastguard Worker   {
110*f6dc9357SAndroid Build Coastguard Worker     if (_bitPos < numBits)
111*f6dc9357SAndroid Build Coastguard Worker     {
112*f6dc9357SAndroid Build Coastguard Worker       _bitPos += 8;
113*f6dc9357SAndroid Build Coastguard Worker       _value = (_value << 8) | Stream.ReadByte();
114*f6dc9357SAndroid Build Coastguard Worker     }
115*f6dc9357SAndroid Build Coastguard Worker     _bitPos -= numBits;
116*f6dc9357SAndroid Build Coastguard Worker     const UInt32 res = _value >> _bitPos;
117*f6dc9357SAndroid Build Coastguard Worker     _value = _value & ((1 << _bitPos) - 1);
118*f6dc9357SAndroid Build Coastguard Worker     return res;
119*f6dc9357SAndroid Build Coastguard Worker   }
120*f6dc9357SAndroid Build Coastguard Worker 
ReadByteFromAligned()121*f6dc9357SAndroid Build Coastguard Worker   Byte ReadByteFromAligned()
122*f6dc9357SAndroid Build Coastguard Worker   {
123*f6dc9357SAndroid Build Coastguard Worker     if (_bitPos == 0)
124*f6dc9357SAndroid Build Coastguard Worker       return Stream.ReadByte();
125*f6dc9357SAndroid Build Coastguard Worker     const unsigned bitsPos = _bitPos - 8;
126*f6dc9357SAndroid Build Coastguard Worker     const Byte b = (Byte)(_value >> bitsPos);
127*f6dc9357SAndroid Build Coastguard Worker     _value = _value & ((1 << bitsPos) - 1);
128*f6dc9357SAndroid Build Coastguard Worker     _bitPos = bitsPos;
129*f6dc9357SAndroid Build Coastguard Worker     return b;
130*f6dc9357SAndroid Build Coastguard Worker   }
131*f6dc9357SAndroid Build Coastguard Worker };
132*f6dc9357SAndroid Build Coastguard Worker 
133*f6dc9357SAndroid Build Coastguard Worker 
134*f6dc9357SAndroid Build Coastguard Worker struct CByteIn
135*f6dc9357SAndroid Build Coastguard Worker {
136*f6dc9357SAndroid Build Coastguard Worker   IByteIn IByteIn_obj;
137*f6dc9357SAndroid Build Coastguard Worker   CBitDecoder BitDecoder;
138*f6dc9357SAndroid Build Coastguard Worker };
139*f6dc9357SAndroid Build Coastguard Worker 
140*f6dc9357SAndroid Build Coastguard Worker 
141*f6dc9357SAndroid Build Coastguard Worker struct CFilter: public NVm::CProgram
142*f6dc9357SAndroid Build Coastguard Worker {
143*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<Byte> GlobalData;
144*f6dc9357SAndroid Build Coastguard Worker   UInt32 BlockStart;
145*f6dc9357SAndroid Build Coastguard Worker   UInt32 BlockSize;
146*f6dc9357SAndroid Build Coastguard Worker   UInt32 ExecCount;
147*f6dc9357SAndroid Build Coastguard Worker 
CFilterCFilter148*f6dc9357SAndroid Build Coastguard Worker   CFilter(): BlockStart(0), BlockSize(0), ExecCount(0) {}
149*f6dc9357SAndroid Build Coastguard Worker };
150*f6dc9357SAndroid Build Coastguard Worker 
151*f6dc9357SAndroid Build Coastguard Worker struct CTempFilter: public NVm::CProgramInitState
152*f6dc9357SAndroid Build Coastguard Worker {
153*f6dc9357SAndroid Build Coastguard Worker   UInt32 BlockStart;
154*f6dc9357SAndroid Build Coastguard Worker   UInt32 BlockSize;
155*f6dc9357SAndroid Build Coastguard Worker   bool NextWindow;
156*f6dc9357SAndroid Build Coastguard Worker 
157*f6dc9357SAndroid Build Coastguard Worker   UInt32 FilterIndex;
158*f6dc9357SAndroid Build Coastguard Worker 
CTempFilterCTempFilter159*f6dc9357SAndroid Build Coastguard Worker   CTempFilter()
160*f6dc9357SAndroid Build Coastguard Worker   {
161*f6dc9357SAndroid Build Coastguard Worker     // all filters must contain at least FixedGlobal block
162*f6dc9357SAndroid Build Coastguard Worker     AllocateEmptyFixedGlobal();
163*f6dc9357SAndroid Build Coastguard Worker   }
164*f6dc9357SAndroid Build Coastguard Worker };
165*f6dc9357SAndroid Build Coastguard Worker 
166*f6dc9357SAndroid Build Coastguard Worker 
167*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_NOQIB_2(
168*f6dc9357SAndroid Build Coastguard Worker   CDecoder
169*f6dc9357SAndroid Build Coastguard Worker   , ICompressCoder
170*f6dc9357SAndroid Build Coastguard Worker   , ICompressSetDecoderProperties2
171*f6dc9357SAndroid Build Coastguard Worker )
172*f6dc9357SAndroid Build Coastguard Worker   bool _isSolid;
173*f6dc9357SAndroid Build Coastguard Worker   bool _solidAllowed;
174*f6dc9357SAndroid Build Coastguard Worker   // bool _errorMode;
175*f6dc9357SAndroid Build Coastguard Worker 
176*f6dc9357SAndroid Build Coastguard Worker   bool _lzMode;
177*f6dc9357SAndroid Build Coastguard Worker   bool _unsupportedFilter;
178*f6dc9357SAndroid Build Coastguard Worker 
179*f6dc9357SAndroid Build Coastguard Worker   CByteIn m_InBitStream;
180*f6dc9357SAndroid Build Coastguard Worker   Byte *_window;
181*f6dc9357SAndroid Build Coastguard Worker   UInt32 _winPos;
182*f6dc9357SAndroid Build Coastguard Worker   UInt32 _wrPtr;
183*f6dc9357SAndroid Build Coastguard Worker   UInt64 _lzSize;
184*f6dc9357SAndroid Build Coastguard Worker   UInt64 _unpackSize;
185*f6dc9357SAndroid Build Coastguard Worker   UInt64 _writtenFileSize; // if it's > _unpackSize, then _unpackSize only written
186*f6dc9357SAndroid Build Coastguard Worker   ISequentialOutStream *_outStream;
187*f6dc9357SAndroid Build Coastguard Worker 
188*f6dc9357SAndroid Build Coastguard Worker   NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize, 9> m_MainDecoder;
189*f6dc9357SAndroid Build Coastguard Worker   UInt32 kDistStart[kDistTableSize];
190*f6dc9357SAndroid Build Coastguard Worker   NHuffman::CDecoder256<kNumHuffmanBits, kDistTableSize, 7> m_DistDecoder;
191*f6dc9357SAndroid Build Coastguard Worker   NHuffman::CDecoder256<kNumHuffmanBits, kAlignTableSize, 6> m_AlignDecoder;
192*f6dc9357SAndroid Build Coastguard Worker   NHuffman::CDecoder256<kNumHuffmanBits, kLenTableSize, 7> m_LenDecoder;
193*f6dc9357SAndroid Build Coastguard Worker 
194*f6dc9357SAndroid Build Coastguard Worker   UInt32 _reps[kNumReps];
195*f6dc9357SAndroid Build Coastguard Worker   UInt32 _lastLength;
196*f6dc9357SAndroid Build Coastguard Worker 
197*f6dc9357SAndroid Build Coastguard Worker   Byte m_LastLevels[kTablesSizesSum];
198*f6dc9357SAndroid Build Coastguard Worker 
199*f6dc9357SAndroid Build Coastguard Worker   Byte *_vmData;
200*f6dc9357SAndroid Build Coastguard Worker   Byte *_vmCode;
201*f6dc9357SAndroid Build Coastguard Worker   NVm::CVm _vm;
202*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<CFilter *> _filters;
203*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<CTempFilter *>  _tempFilters;
204*f6dc9357SAndroid Build Coastguard Worker   unsigned _numEmptyTempFilters;
205*f6dc9357SAndroid Build Coastguard Worker   UInt32 _lastFilter;
206*f6dc9357SAndroid Build Coastguard Worker 
207*f6dc9357SAndroid Build Coastguard Worker   UInt32 PrevAlignBits;
208*f6dc9357SAndroid Build Coastguard Worker   UInt32 PrevAlignCount;
209*f6dc9357SAndroid Build Coastguard Worker 
210*f6dc9357SAndroid Build Coastguard Worker   bool TablesRead;
211*f6dc9357SAndroid Build Coastguard Worker   bool TablesOK;
212*f6dc9357SAndroid Build Coastguard Worker   bool PpmError;
213*f6dc9357SAndroid Build Coastguard Worker 
214*f6dc9357SAndroid Build Coastguard Worker   int PpmEscChar;
215*f6dc9357SAndroid Build Coastguard Worker   CPpmd7 _ppmd;
216*f6dc9357SAndroid Build Coastguard Worker 
217*f6dc9357SAndroid Build Coastguard Worker   HRESULT WriteDataToStream(const Byte *data, UInt32 size);
218*f6dc9357SAndroid Build Coastguard Worker   HRESULT WriteData(const Byte *data, UInt32 size);
219*f6dc9357SAndroid Build Coastguard Worker   HRESULT WriteArea(UInt32 startPtr, UInt32 endPtr);
220*f6dc9357SAndroid Build Coastguard Worker   void ExecuteFilter(unsigned tempFilterIndex, NVm::CBlockRef &outBlockRef);
221*f6dc9357SAndroid Build Coastguard Worker   HRESULT WriteBuf();
222*f6dc9357SAndroid Build Coastguard Worker 
223*f6dc9357SAndroid Build Coastguard Worker   void InitFilters();
224*f6dc9357SAndroid Build Coastguard Worker   bool AddVmCode(UInt32 firstByte, UInt32 codeSize);
225*f6dc9357SAndroid Build Coastguard Worker   bool ReadVmCodeLZ();
226*f6dc9357SAndroid Build Coastguard Worker   bool ReadVmCodePPM();
227*f6dc9357SAndroid Build Coastguard Worker 
228*f6dc9357SAndroid Build Coastguard Worker   UInt32 ReadBits(unsigned numBits);
229*f6dc9357SAndroid Build Coastguard Worker 
230*f6dc9357SAndroid Build Coastguard Worker   HRESULT InitPPM();
231*f6dc9357SAndroid Build Coastguard Worker   // int DecodePpmSymbol();
232*f6dc9357SAndroid Build Coastguard Worker   HRESULT DecodePPM(Int32 num, bool &keepDecompressing);
233*f6dc9357SAndroid Build Coastguard Worker 
234*f6dc9357SAndroid Build Coastguard Worker   HRESULT ReadTables(bool &keepDecompressing);
235*f6dc9357SAndroid Build Coastguard Worker   HRESULT ReadEndOfBlock(bool &keepDecompressing);
236*f6dc9357SAndroid Build Coastguard Worker   HRESULT DecodeLZ(bool &keepDecompressing);
237*f6dc9357SAndroid Build Coastguard Worker   HRESULT CodeReal(ICompressProgressInfo *progress);
238*f6dc9357SAndroid Build Coastguard Worker 
InputEofError()239*f6dc9357SAndroid Build Coastguard Worker   bool InputEofError() const { return m_InBitStream.BitDecoder.ExtraBitsWereRead(); }
InputEofError_Fast()240*f6dc9357SAndroid Build Coastguard Worker   bool InputEofError_Fast() const { return (m_InBitStream.BitDecoder.Stream.NumExtraBytes > 2); }
241*f6dc9357SAndroid Build Coastguard Worker 
CopyBlock(UInt32 dist,UInt32 len)242*f6dc9357SAndroid Build Coastguard Worker   void CopyBlock(UInt32 dist, UInt32 len)
243*f6dc9357SAndroid Build Coastguard Worker   {
244*f6dc9357SAndroid Build Coastguard Worker     _lzSize += len;
245*f6dc9357SAndroid Build Coastguard Worker     UInt32 pos = (_winPos - dist - 1) & kWindowMask;
246*f6dc9357SAndroid Build Coastguard Worker     Byte *window = _window;
247*f6dc9357SAndroid Build Coastguard Worker     UInt32 winPos = _winPos;
248*f6dc9357SAndroid Build Coastguard Worker     if (kWindowSize - winPos > len && kWindowSize - pos > len)
249*f6dc9357SAndroid Build Coastguard Worker     {
250*f6dc9357SAndroid Build Coastguard Worker       const Byte *src = window + pos;
251*f6dc9357SAndroid Build Coastguard Worker       Byte *dest = window + winPos;
252*f6dc9357SAndroid Build Coastguard Worker       _winPos += len;
253*f6dc9357SAndroid Build Coastguard Worker       do
254*f6dc9357SAndroid Build Coastguard Worker         *dest++ = *src++;
255*f6dc9357SAndroid Build Coastguard Worker       while (--len != 0);
256*f6dc9357SAndroid Build Coastguard Worker       return;
257*f6dc9357SAndroid Build Coastguard Worker     }
258*f6dc9357SAndroid Build Coastguard Worker     do
259*f6dc9357SAndroid Build Coastguard Worker     {
260*f6dc9357SAndroid Build Coastguard Worker       window[winPos] = window[pos];
261*f6dc9357SAndroid Build Coastguard Worker       winPos = (winPos + 1) & kWindowMask;
262*f6dc9357SAndroid Build Coastguard Worker       pos = (pos + 1) & kWindowMask;
263*f6dc9357SAndroid Build Coastguard Worker     }
264*f6dc9357SAndroid Build Coastguard Worker     while (--len != 0);
265*f6dc9357SAndroid Build Coastguard Worker     _winPos = winPos;
266*f6dc9357SAndroid Build Coastguard Worker   }
267*f6dc9357SAndroid Build Coastguard Worker 
PutByte(Byte b)268*f6dc9357SAndroid Build Coastguard Worker   void PutByte(Byte b)
269*f6dc9357SAndroid Build Coastguard Worker   {
270*f6dc9357SAndroid Build Coastguard Worker     const UInt32 wp = _winPos;
271*f6dc9357SAndroid Build Coastguard Worker     _window[wp] = b;
272*f6dc9357SAndroid Build Coastguard Worker     _winPos = (wp + 1) & kWindowMask;
273*f6dc9357SAndroid Build Coastguard Worker     _lzSize++;
274*f6dc9357SAndroid Build Coastguard Worker   }
275*f6dc9357SAndroid Build Coastguard Worker 
276*f6dc9357SAndroid Build Coastguard Worker public:
277*f6dc9357SAndroid Build Coastguard Worker   CDecoder();
278*f6dc9357SAndroid Build Coastguard Worker   ~CDecoder();
279*f6dc9357SAndroid Build Coastguard Worker };
280*f6dc9357SAndroid Build Coastguard Worker 
281*f6dc9357SAndroid Build Coastguard Worker }}
282*f6dc9357SAndroid Build Coastguard Worker 
283*f6dc9357SAndroid Build Coastguard Worker #endif
284